iOS 新特性指南

最新更新:2022-11-29

iOS 14 New Features

iOS 14 的新特性主要包含 APP Clip、剪切板以及隱私保護等新特性,並無通知相關的新特性。

iOS 13 New Features

iOS 13 的新特性主要包含 Drak Mode、Swift UI 等新特性,並無通知相關的新特性。

iOS 12 New Features

推播分組

iOS 12 中同一類型的通知會被合成一個通知組,用戶可以通過點擊通知組展開組裡的所有通知

通知分組使用兩種分組方式:自動分組(Automatic grouping)和線程標識(Thread identifier)。開發者不需要對自動分組做額外的操作,系統會根據 App 的 bundleId 對推播進行分組。如果需要對通知做更細緻的分組就需要用上線程標識了。

用戶可以對分組進行設置(自動、按應用程式、關閉)

線程標識(Thread identifier)這個屬性在 iOS10 就已經存在,但是在 iOS12 才真正實現分組功能。

// The unique identifier for the thread or conversation related to this notification request. It will be used to visually group notifications together. @property (NS_NONATOMIC_IOSONLY, copy) NSString *threadIdentifier __TVOS_PROHIBITED;
          // The unique identifier for the thread or conversation related to this notification request. It will be used to visually group notifications together.
@property (NS_NONATOMIC_IOSONLY, copy) NSString *threadIdentifier __TVOS_PROHIBITED;

        
此代碼塊在浮窗中顯示

摘要格式設置

通知自動分組後,在最下邊會有一個訊息摘要。默認格式是: 還有 n 個通知。這個格式是可以定制的。 第一種: 通過 UNNotificationCategory 進行格式定制

+ (instancetype)categoryWithIdentifier:(NSString *)identifier actions:(NSArray<UNNotificationAction *> *)actions intentIdentifiers:(NSArray<NSString *> *)intentIdentifiers hiddenPreviewsBodyPlaceholder:(nullable NSString *)hiddenPreviewsBodyPlaceholder categorySummaryFormat:(nullable NSString *)categorySummaryFormat options:(UNNotificationCategoryOptions)options __IOS_AVAILABLE(12.0) __WATCHOS_PROHIBITED;
          + (instancetype)categoryWithIdentifier:(NSString *)identifier
                               actions:(NSArray<UNNotificationAction *> *)actions
                     intentIdentifiers:(NSArray<NSString *> *)intentIdentifiers
         hiddenPreviewsBodyPlaceholder:(nullable NSString *)hiddenPreviewsBodyPlaceholder
                 categorySummaryFormat:(nullable NSString *)categorySummaryFormat
                               options:(UNNotificationCategoryOptions)options __IOS_AVAILABLE(12.0) __WATCHOS_PROHIBITED;

        
此代碼塊在浮窗中顯示

第二種: 通過 UNNotificationContent 進行定制

/// The argument to be inserted in the summary for this notification. @property (NS_NONATOMIC_IOSONLY, readonly, copy) NSString *summaryArgument __IOS_AVAILABLE(12.0) __WATCHOS_PROHIBITED __TVOS_PROHIBITED; /// A number that indicates how many items in the summary are represented in the summary. /// For example if a podcast app sends one notification for 3 new episodes in a show, /// the argument should be the name of the show and the count should be 3. /// Default is 1 and cannot be 0. @property (NS_NONATOMIC_IOSONLY, readonly, assign) NSUInteger summaryArgumentCount __IOS_AVAILABLE(12.0) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;
          /// The argument to be inserted in the summary for this notification.
@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSString *summaryArgument __IOS_AVAILABLE(12.0) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;

/// A number that indicates how many items in the summary are represented in the summary.
/// For example if a podcast app sends one notification for 3 new episodes in a show,
/// the argument should be the name of the show and the count should be 3.
/// Default is 1 and cannot be 0.
@property (NS_NONATOMIC_IOSONLY, readonly, assign) NSUInteger summaryArgumentCount __IOS_AVAILABLE(12.0) __WATCHOS_PROHIBITED __TVOS_PROHIBITED;

        
此代碼塊在浮窗中顯示

通知管理

蘋果針對訊息增加了一個 "管理" 的按鈕,訊息左滑即可出現。

臨時授權

臨時授權主要體現就是推播訊息過來會有兩個按鈕,會主動讓用戶自己選擇

警告通知

比如家庭安全、健康、公共安全等因素的時候。此訊息需要用戶必須採取行動。最簡單的一個場景是家里安裝了一個攝像頭,我們去上班了,此時如果家中有人,則攝像頭會推播訊息給我們。這類通知需要申請特別的證書。

iOS 10 New Features

說明

iOS 10 新增了大量關於通知的新特性,詳情參照 Engagelab 官方的 Blog。 請跳轉至:iOS 10 新特性

iOS 10 Service Extension

說明

iOS 10 新增了 Service Extension 官方給出的說明圖如下 這意味著在 APNs 到達我們的設備之前,還會經過一層允許用戶自主設置的 Extension 服務進行處理,為 APNs 增加了多樣性。

使用方法

Service Extension 使用起來很容易上手,首先我們需要創建一個 Service Extension 服務, 如下圖

然後這裡需要注意幾個點

  • Service Extension 的 Bundle Identifier 不能和 Main Target(也就是你自己的 App Target)的 Bundle Identifier 相同,否則會報 BundeID 重複的錯誤。
  • Service Extension 的 Bundle Identifier 需要在 Main Target 的命名空間下,比如說 Main Target 的 BundleID 為 io.mtpush.xxx,那麼 Service Extension 的 BundleID 應該類似與 io.mtpush.xxx.yyy 這樣的格式。如果不這麼做,你可能會遇到一個錯誤。

那麼現在你的 Service Extension 服務已經創建成功了,此時你已經成功的使用了 Service Extension,但是好像我們還沒有對它做什麼操作,看看你的項目,你得到了一個類,這個類中包含兩個方法。

  • didReceiveNotificationRequest:(UNNotificationRequest _)request withContentHandler:(void (^)(UNNotificationContent _contentToDeliver))contentHandler
  • serviceExtensionTimeWillExpire

我們來看一下第一個方法的官方解釋:Call contentHandler with the modified notification content to deliver. If the handler is not called before the service's time expires then the unmodified notification will be delivered。 簡單解釋一下,APNs 到來的時候會調用這個方法,此時你可以對推播過來的內容進行處理,然後使用 contentHandler 完成這次處理。但是如果時間太長了,APNs 就會原樣顯示出來。 也就是說,我們可以在這個方法中處理我們的通知,個性化展示給用戶。 而第二個方法,是對第一個方法的補救。第二個方法會在過期之前進行回調,此時你可以對你的 APNs 訊息進行一下緊急處理。

iOS 9 集成

iOS 9 變動影響 SDK 部分:

  • 增加了 bitCode 編碼格式, 當 SDK 不支持 bitCode 時,用戶集成時無法開啟 bitCode 選項.
    • 現象: 用戶集成 SDK 後無法編譯通過,錯誤日誌裡包含了 bitCode 的相關錯誤信息
  • 默認使用 https 連接, 如果請求為 http, 需要手動配置 plist 來支持 http 服務,當前我們的服務器請求都走 http 服務。
    • 現象: 用戶集成 SDK 後,所有 MTPush 相關的 http 服務都提示連接錯誤或者連接超時, 可能是此問題。

bitCode 解決方式

  • MTPush iOS SDK v1.8.7 及以上版本的 SDK, 已經增加對 iOS 9 新特性 bitCode 的支持。

Https 解決方式

MTPush 2.0.0 及以上的版本則不需要配置此步驟

  • 需要用戶主動在當前項目的 Info.plist 中添加 NSAppTransportSecurity 類型 Dictionary。
  • 在 NSAppTransportSecurity 下添加 NSAllowsArbitraryLoads 類型 Boolean, 值設為 YES

iOS 9 UIUserNotificationActionBehaviorTextInput

支持版本

v1.8.0 版本開始

  1. 本次 iOS 9 在推播方面最大的變化就是修改了推播 Category 的類型,在原本的推播 categories 的基礎上,增加了一個 text Action 類型,這個參數的目的是用來註冊通過通知快捷文字輸入的事項。
  2. 這個 categories 由一系列的 UIUserNotificationCategory 組成。每個 UIUserNotificationCategory 對象允許添加一組 UIMutableUserNotificationAction 類型的參數來增加通知欄上的項目。如今 iOS9 在原有的 UIMutableUserNotificationAction 類型增加了 Text 輸入類型(UIUserNotificationActionBehaviorTextInput), 通過 behavior 來設置(只有 iOS9 才擁有的屬性)。
  3. 回調的方法 iOS9 使用了兩個新的回調方法來處理點擊按鈕的事件:
- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullableNSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler NS_AVAILABLE_IOS(9_0) - (void)application:(UIApplication *)application handleActionWithIdentifier:(nullableNSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler NS_AVAILABLE_IOS(9_0)
          - (void)application:(UIApplication *)application handleActionWithIdentifier:(nullableNSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler NS_AVAILABLE_IOS(9_0)

- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullableNSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler NS_AVAILABLE_IOS(9_0)

        
此代碼塊在浮窗中顯示

說明:

  • 當 Action 為 UIUserNotificationActionBehaviorTextInput 時, 需要通過 responseInfo 的 UIUserNotificationActionResponseTypedTextKey 來獲取輸入的文字內容,UIUserNotificationTextInputActionButtonTitleKey 獲取點擊的按鈕類型.
  • 當 Action 為 UIUserNotificationActionBehaviorDefault 時,responseInfo 為 nil, 通過 identifier 來區分點擊按鈕分別是什麼來做處理.

客戶端設置

設置帶有快速回复內容的通知

# ifdef __IPHONE_9_0 UIMutableUserNotificationAction *replyAction = [[UIMutableUserNotificationAction alloc]init]; replyAction.title = @"Reply"; replyAction.identifier = @"comment-reply"; replyAction.activationMode = UIUserNotificationActivationModeBackground; replyAction.behavior = UIUserNotificationActionBehaviorTextInput; UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc]init]; category.identifier = @"reply"; [category setActions:@[replyAction] forContext:UIUserNotificationActionContextDefault]; # endif
          # ifdef __IPHONE_9_0 
 UIMutableUserNotificationAction *replyAction = [[UIMutableUserNotificationAction alloc]init];
 replyAction.title = @"Reply";
 replyAction.identifier = @"comment-reply";
 replyAction.activationMode = UIUserNotificationActivationModeBackground;
 replyAction.behavior = UIUserNotificationActionBehaviorTextInput;
  
 UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc]init];
 category.identifier = @"reply";
 [category setActions:@[replyAction] forContext:UIUserNotificationActionContextDefault];
# endif

        
此代碼塊在浮窗中顯示

使用回調函數

- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler NS_AVAILABLE_IOS(9_0) {if ([identifier isEqualToString:@"comment-reply"]) {NSString *response = responseInfo[UIUserNotificationActionResponseTypedTextKey]; // 對輸入的文字作處理 } completionHandler();}
          - (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler NS_AVAILABLE_IOS(9_0) {if ([identifier isEqualToString:@"comment-reply"]) {NSString *response = responseInfo[UIUserNotificationActionResponseTypedTextKey];
 // 對輸入的文字作處理
 }
 completionHandler();}

        
此代碼塊在浮窗中顯示

服務端設置

服務端 payload 格式:aps 增加 category 字段,當該字段與客戶端 UIMutableUserNotificationCategory 的 identifier 匹配時,觸發設定的 action 和 button 顯示。

payload example: {"aps":{"alert":"example", "sound":"default", "badge": 1, "category":"reply"}}
          payload example:
{"aps":{"alert":"example", "sound":"default", "badge": 1, "category":"reply"}}

        
此代碼塊在浮窗中顯示

iOS 8 UILocalNotification

本次 iOS 8 UILocalNotification 增加了三個參數: region、regionTriggersOnce、category。

  • region: 用於控制當用戶進入或者離開某一個地理位置時候,觸發通知。使用此功能,用戶需要擁有 CoreLocation 的 "when-in-use" 權限。
  • regionTriggersOnce(BOOL):當為 YES 時,通知只會觸發一次,當為 NO 時,通知將會在每一次進入或者離開時都觸發。
  • category: 如果 localNotification 通過 +[UIUserNotificationSettings settingsForUserNotificationTypes:userNotificationActionSettings:]註冊了,通過該 category 可以獲取該通知的註冊 category.

客戶端設置

使用 UILocalNotification

// set localNotification CLLocationCoordinate2D coordinate2D; coordinate2D.latitude = 100.0; coordinate2D.longitude = 100.0; CLRegion *currentRegion = [[CLCircularRegion alloc] initWithCenter:coordinate2D radius:CLLocationDistanceMax identifier:@"test"]; [APService setLocalNotification:[NSDate dateWithTimeIntervalSinceNow:120] alertBody:@"test ios8 notification" badge:0 alertAction:@"取消" identifierKey:@"1" userInfo:nil soundName:nil region:currentRegion regionTriggersOnce:YES category:@"test"];
          // set localNotification
  CLLocationCoordinate2D coordinate2D;
  coordinate2D.latitude = 100.0;
  coordinate2D.longitude = 100.0;
  CLRegion *currentRegion =
      [[CLCircularRegion alloc] initWithCenter:coordinate2D
                                        radius:CLLocationDistanceMax
                                    identifier:@"test"];
 
  [APService setLocalNotification:[NSDate dateWithTimeIntervalSinceNow:120]
                        alertBody:@"test ios8 notification"
                            badge:0
                      alertAction:@"取消"
                    identifierKey:@"1"
                         userInfo:nil
                        soundName:nil
                           region:currentRegion
               regionTriggersOnce:YES
                         category:@"test"];

        
此代碼塊在浮窗中顯示

iOS 8 UIUserNotificationSettings

支持版本

v1.8.0 版本開始。

客戶端設置

使用 UIUserNotificationCategory

if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {NSMutableSet *categories = [NSMutableSet set]; UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init]; category.identifier = @"identifier"; UIMutableUserNotificationAction *action = [[UIMutableUserNotificationAction alloc] init]; action.identifier = @"test2"; action.title = @"test"; action.activationMode = UIUserNotificationActivationModeBackground; action.authenticationRequired = YES; //YES 顯示為紅色,NO 顯示為藍色 action.destructive = NO; NSArray *actions = @[action]; [category setActions:actions forContext:UIUserNotificationActionContextMinimal]; [categories addObject:category]; }
          if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {NSMutableSet *categories = [NSMutableSet set];
 
 UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init];
 
 category.identifier = @"identifier";
 
 UIMutableUserNotificationAction *action = [[UIMutableUserNotificationAction alloc] init];
 
 action.identifier = @"test2";
 
 action.title = @"test";
 
 action.activationMode = UIUserNotificationActivationModeBackground;
 
 action.authenticationRequired = YES;
 
 //YES 顯示為紅色,NO 顯示為藍色
 action.destructive = NO;
 
 NSArray *actions = @[action];
 
 [category setActions:actions forContext:UIUserNotificationActionContextMinimal];
 
 [categories addObject:category];
}

        
此代碼塊在浮窗中顯示

使用 UIUserNotificationType

if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {[APService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:categories]; }else{[APService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil]; }
          if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {[APService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)                      categories:categories];
}else{[APService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert)                      categories:nil];
}

        
此代碼塊在浮窗中顯示

使用回調函數

// Called when your app has been activated by the user selecting an action from // a remote notification. // A nil action identifier indicates the default action. // You should call the completion handler as soon as you've finished handling // the action. - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {}
          // Called when your app has been activated by the user selecting an action from
// a remote notification.
// A nil action identifier indicates the default action.
// You should call the completion handler as soon as you've finished handling
// the action.
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo
  completionHandler:(void (^)())completionHandler {}

        
此代碼塊在浮窗中顯示

服務端設置

服務端 payload 格式:aps 增加 category 字段,當該字段與客戶端 UIMutableUserNotificationCategory 的 identifier 匹配時,觸發設定的 action 和 button 顯示。

payload example: {"aps":{"alert":"example", "sound":"default", "badge": 1, "category":"identifier"}}
          payload example:
{"aps":{"alert":"example", "sound":"default", "badge": 1, "category":"identifier"}}

        
此代碼塊在浮窗中顯示

iOS 7 Background Remote Notification

本次 iOS 7 在推播方面最大的變化就是允許,應用程式收到通知後在後台(background)狀態下運行一段代碼,可用於從服務器獲取內容更新。功能使用場景:(多媒體)聊天,Email 更新,基於通知的訂閱內容同步等功能,提升了終端用戶的體驗。

Remote Notifications 與之前版本的對比可以參考下面兩張 Apple 官方的圖片便可一目了然。

如果只攜帶 content-available: 1 不攜帶任何 badge,sound 和訊息內容等參數,則可以不打擾用戶的情況下進行內容更新等操作即為“Silent Remote Notifications”。

客戶端設置

開啟 Remote notifications

需要在 Xcode 中修改應用程式的 Capabilities 開啟 Remote notifications,請參考下圖:

修改通知處理函數

當註冊了 Backgroud Modes -> Remote notifications 後,notification 處理函數一律切換到下面函數,後台推播代碼也在此函數中調用。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
          - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;

        
此代碼塊在浮窗中顯示

服務端推播設置

推播訊息攜帶 content-available: 1 是 Background 運行的必須參數,如果不攜帶此字段則與 iOS7 之前版本的普通推播一樣。

使用 Web Portal 推播

在“可選設置內”選擇對應的參數。

image.png

使用 API 推播

只需在 Push API v3 的 ios 內附加 content-available":true 字段即可

限制與註意

  • “Silent Remote Notifications”是在 Apple 的限制下有一定的頻率控制,但具體頻率不詳。所以並不是所有的 “Silent Remote Notifications” 都能按照預期到達客戶端觸發函數。
  • “Background”下提供給應用程式的運行時間窗是有限制的,如果需要下載較大的文件請參考 Apple 的 NSURLSession 的介紹。
  • “Background Remote Notification” 的前提是要求客戶端處於 Background 或 Suspended 狀態,如果用戶通過 App Switcher 將應用程式從後台 Kill 掉應用程式將不會喚醒應用程式處理 background 代碼。

更詳細的說明資料請查閱 Apple 官方的 iOS 開發文檔。

在文档中心打开