iOS10發布以來,相信各位開發者能踩的坑也應該踩得差不多了;但也許正是因為每次蘋果都會更新比較多的東西,才會覺得搞iOS很有意思吧。(不知道大家會不會覺得樓主這種想法有點坑?)
推送是iOS10系統變動比較大的一個地方,對於這種大變動不瞅瞅一下著實不符合樓主的性格,那麼樓主就在求知欲的推動下(畢竟還得給自己的項目進行適配不是..)就花了點時間對UserNotifications這個框架進行了一個整體的了解,希望在這裡記錄一下,希望能夠幫助對這個框架有興趣的小伙伴。
如果大家的項目中推送是使用了極光、友盟等第三方推送,那麼請根據他們的官方文檔以及最新的SDK對iOS10進行適配即可,跟著文檔一步一步走也比較簡單。但是如果想要真實的了解原框架的流程,建議還是使用原生推送吧,樓主本文博客下使用的就是原生推送。
如何配置原生推送,推薦有夢想的蝸牛 一步一步教你做ios推送,這位博主寫的很詳細,雖然開發者界面已經不是那樣子了,但實質的東西還是沒有變化的。如果按照推薦博文的配置(!一定要確認所有的配置都沒有問題!),但依舊收不到遠程推送,那麼估計就和樓主一樣“中獎”了,可能是PHP端交互出問題了,這個時候推薦大家使用PushMeBody來完成遠程推送。(使用PushMesBody中的device token直接復制打印的device token即可,不需要去掉空格)
為了能夠區分它與之前用法的異同,樓主還是盡可能的想通過比較的方法實現推送的相關功能。
所有coding都在 RITL/RITLPushNoticationDemo(如果有幫助,請Star表示支持一下,感謝)。
如果有什麼問題,也請及時指出,共同進步,感謝。
注冊的位置沒有任何的變化,是在Appdelegate中的-application: didFinishLaunchingWithOptions:方法裡面進行注冊,樓主為了簡化它的代碼,將注冊功能封裝成了一個RITLNotificationManager類,所以該方法下只需一句話即可:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. //初始化個數 [UIApplication sharedApplication].applicationIconBadgeNumber = 0; //注冊所有的推送 [[RITLNotificationManager sharedInstance]registerRemoteNotificationsApplication:self]; return YES; }
RITLNotificationManager的聲明(樓主在聲明文件中使用了預編譯進行方法的聲明,實際的開發中建議不要這麼寫,將方法分開便是,不同的版本使用不同的方法即可)以及實現方法如下:
//RITLNotificationManager.h(實際Demo中它在"RITLOriginPushAppDelegate+RITLNotificationManager.h"文件下) /// 注冊遠程推送 #ifdef __IPHONE_10_0 - (void)registerRemoteNotificationsApplication:(id)application; #else - (void)registerRemoteNotificationsApplication:(id)application; #endif
//RITLOriginPushAppDelegate+RITLNotificationManager.m #ifdef __IPHONE_10_0 -(void)registerRemoteNotificationsApplication:(id)application #else - (void)registerRemoteNotificationsApplication:(id)application #endif { #ifdef __IPHONE_10_0 //設置代理對象 [UNUserNotificationCenter currentNotificationCenter].delegate = application; // 請求權限 [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:UNAuthorizationOptionBadge|UNAuthorizationOptionSound|UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted == true)//如果准許,注冊推送 { [[UIApplication sharedApplication]registerForRemoteNotifications]; } }]; #else #ifdef __IPHONE_8_0 //適配iOS 8 [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil]]; [[UIApplication sharedApplication]registerForRemoteNotifications]; #else //適配iOS7 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert]; #endif #endif }
這一部分iOS10沒有發生變化,還是和之前一樣,分為注冊成功以及注冊失敗兩個協議方法,方法就在類別RITLOriginPushAppDelegate+RITLNotificationManager:
// 注冊推送成功 -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // NSLog(@"token = %@",deviceToken); // 將返回的token發送給服務器 } // 注冊推送失敗 -(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"remoteNotice failture = %@",error.localizedDescription); }
在Demo中對AppDelegate新建了一個類別"RITLOriginPushAppDelegate+RITLOldNotification"來完成對之前推送消息的接收以及處理:
//通過點擊遠程推送進入App執行的方法,不管是應用被殺死還是位於後台 -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { //收到的信息 NSLog(@"%@",[[userInfo valueForKey:@"aps"] valueForKey:@"alert"]); [self performSelector:NSSelectorFromString(@"__showAlert:") withObject:@"通過點擊推送進入App" afterDelay:0]; }
// 在前台收到遠程推送執行的方法,如果實現了iOS10的協議方法,該方法不執行,雖然沒有標明廢棄 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { //這個時候不會彈出推送,通常,在此處進行一次本地推送,進行通知 //coding.. //回調 completionHandler(UIBackgroundFetchResultNewData); }
// 收到本地推送 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { //coding to handle local notification NSLog(@"本地推送啦!"); //獲得文本與詳細內容 NSString * content = [NSString stringWithFormat:@"本地通知:title = %@, subTitle = %@",notification.alertBody,notification.alertTitle]; [self performSelector:NSSelectorFromString(@"__showAlert:") withObject:content afterDelay:1]; }
由於UserNotifications不再對遠程推送以及本地推送進行區分,所以只需實現UNUserNotificationCenterDelegate協議下的兩個協議方法即可,樓主是將該方法寫在了AppDelegate的另一類別中RITLOriginPushAppDelegate+RITLUserNotifications:
#pragma mark -// 在前台收到通知時,將要彈出通知的時候觸發 - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler { //比如如果App實在前台,就不需要Badge了 if([UIApplication sharedApplication].applicationState == UIApplicationStateActive) { completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert); } else//如果是後台或者不活躍狀態,需要badge { //需要三種彈出形式,如果存在Alert,那麼App在前台也是可以從上面彈出的 completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert); } }
// 已經收到通知響應的處理方法,不管是什麼通知,當通過點擊推送進入或者回到App的時候觸發 - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler { //獲得響應對象 UNNotification * notification = response.notification; //獲得響應時間 // NSDate * responseDate = notification.date; //獲得響應體 UNNotificationRequest * request = notification.request; //獲得響應體的標識符 // NSString * identifier = request.identifier; // 喚起通知的對象 // UNNotificationTrigger * trigger = request.trigger; //獲得通知內容 UNNotificationContent * content = request.content; //比如獲得我想要的alert NSString * alertString = content.body; //可以彈出Alert提示一下 [self performSelector:NSSelectorFromString(@"__showAlert:") withObject:alertString afterDelay:1]; //比如這裡可以進行界面的跳轉等操作... //告知完成 completionHandler(); }
以上配置完畢後,使用PushMeBaby進行推送預覽一下,以下是推送的內容。
具體內容的格式如下:具體格式摘自簡書博主linatan博文-iOS10-UserNotifications
{ "aps": { "alert": { "title":"hello", "subtitle" : "Session 01", "body":"it is a beautiful day" }, "category":"helloIdentifier",//比如我們想要使用自定義的UI,可以通過該值設置當前request對象的identifier "badge":1, "mutable-content":1,//如果想要啟用Service的拓展,需要此數據,這個後面會有介紹 "sound":"default", "image":"https://picjumbo.imgix.net/HNCK8461.jpg?q=40&w=200&sharp=30" } }
在進行測試的過程中,樓主使用的遠程推送如下:
//Demo中進行推送的內容如下: { "aps": { "alert" : "This is My message Yue.", "badge" : "1", "mutable-content" : 1 } } //pushMeBody中推送的字符串 self.payload = @"{\"aps\":{\"alert\":\"This is My message Yue.\",\"badge\":\"1\",\"mutable-content\":1}}";
後台接收的推送、響應3D Touch的推送以及點擊推送進入App後的效果如下:
對於Demo中大部分的測試,樓主都是使用了本地推送,所以樓主將推送功能封裝成了RITLPushMessageManager類,聲明方法如下:
/// iOS10之前的本地推送 - (void)pushLocationNotificationbeforeiOS10; //由於iOS10推送的可更新性,還新增了一個枚舉,當然,本來是不需要的,但為了測試才有的這個枚舉類型 typedef NS_ENUM(NSUInteger, RITLPushMessageType) { RITLPushMessageTypeNew = 0, /**<默認為推送新的推送通知*/ RITLPushMessageTypeUpdate = 1, /**<更新當前的推送通知*/ }; /// iOS10 之後的本地推送,並根據類型選擇是新的推送還是更新 - (void)pushLicationNotification:(nullable NSArray*)attachments pushType:(RITLPushMessageType)type NS_AVAILABLE_IOS(10_0);
這個推送相信大家都是比較熟的了,使用iOS10建議廢棄的UILocalNotification類,實現方法如下:
-(void)pushLocationNotificationbeforeiOS10 { UILocalNotification * localNotification = [[UILocalNotification alloc]init]; //設置消息體 localNotification.alertBody = @"RITL send a location notications (iOS9)"; #ifdef __IPHONE_8_2 //設置詳細內容,iOS8.2才存在 localNotification.alertTitle = @"I am SubTitle"; #endif //設置彈出時的圖 localNotification.alertLaunchImage = @"Stitch.png"; #ifdef __IPHONE_8_0 //拓展id localNotification.category = RITLRequestIdentifier; #endif //觸發聲音 localNotification.soundName = UILocalNotificationDefaultSoundName; //觸發標志 localNotification.applicationIconBadgeNumber = 1; //1秒之後觸發 localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1]; //注冊通知 [[UIApplication sharedApplication] scheduleLocalNotification:localNotification]; }
在新的框架下,所有的推送都是使用了UNNotificationRequest類,這裡有一點需要注意: 媒體的url可以存儲在UNNotificationAttachment類之中,但是必須是本地路徑,如果是網絡圖,需要先從網絡下載下來,存到本地,然後將本地的路徑存儲進行處理;如果UNNotificationAttachment對象初始化失敗,會拋出異常,導致程序崩潰。比如Demo中就是通過選擇相冊的照片進行本地化,再賦值路徑來進行的本地推送實現方法如下:
-(void)pushLicationNotification:(NSArray*)attachments pushType:(RITLPushMessageType)type { NSString * subTitle = (type == RITLPushMessageTypeNew ? @"I am a new SubTitle" : @"I am a update SubTitle"); //初始化信息對象 UNMutableNotificationContent * content = [[UNMutableNotificationContent alloc]init]; //設置內容 content.body = @"RITL send a location notications"; //設置詳細內容 content.subtitle = subTitle; //設置圖片名稱 content.launchImageName = @"Stitch.png"; //設置拓展id content.categoryIdentifier = RITLRequestIdentifier; //設置推送聲音 content.sound = [UNNotificationSound defaultSound]; //設置通知 content.badge = @1; //設置附帶信息 content.userInfo = @{@"RITL":@"I am RITL.",@"network":@"https://www.baidu.com"}; //媒體附帶信息 content.attachments = attachments; #pragma mark - 延時發送 UNTimeIntervalNotificationTrigger * trigger = [UNNotificationTrigger defaultTimeIntervalNotificationTrigger]; //初始化通知請求 UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:RITLRequestIdentifier content:content trigger:trigger]; //如果是更新,先移除 if (type == RITLPushMessageTypeUpdate) [[UNUserNotificationCenter currentNotificationCenter]removeDeliveredNotificationsWithIdentifiers:@[RITLRequestIdentifier]]; //獲得推送控制中心 [[UNUserNotificationCenter currentNotificationCenter]addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { if(error != nil)//出錯 { NSLog(@"error = %@",error.localizedDescription); } }]; }
可能名字翻譯的不是那麼正確,但個人的理解,它就是負責觸發條件的,比如Demo中的類別UNNotificationTrigger+RITLConveniceInitialize中,為Demo提供了三種默認的觸發條件,如下:
///默認的延時推送觸發時機 +(UNTimeIntervalNotificationTrigger *)defaultTimeIntervalNotificationTrigger { return [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:false]; }
/// 默認的日歷推送觸發時機 +(UNCalendarNotificationTrigger *)defaultCalendarNotificationTrigger { NSDateComponents * dateCompents = [NSDateComponents new]; dateCompents.hour = 7;//表示每天的7點進行推送 return [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:dateCompents repeats:true]; }
/// 默認的地域推送觸發時機 +(UNLocationNotificationTrigger *)defaultLocationNotificationTrigger { // 因為CLRegion類的初始化方法在iOS7提示廢棄,改用它的子類CLCircularRegion // CLRegion * region = [CLRegion alloc]initCircularRegionWithCenter:cooddinate2D(100,100) radius:200 identifier:locationTriggerIdentifier //經緯度分別都是100 CLLocationCoordinate2D coordinate2D = cooddinate2D(100,100); //初始化范圍類 CLCircularRegion * region = [[CLCircularRegion alloc]initWithCenter:coordinate2D radius:200 identifier:locationTriggerIdentifier]; return [UNLocationNotificationTrigger triggerWithRegion:region repeats:false]; }
樓主選擇使用在本地相冊中選擇一個圖片來完成本地推送,大體思路如下:
//該過程通過類別UNNotificationAttachment+RITLConceniceInitialize實現 +(NSArray*)defaultNotificationAttachmentsWithImage:(UIImage *)image { if (image == nil) return nil; NSMutableArray * attachments = [NSMutableArray arrayWithCapacity:1]; //將image存到本地 [RITLPushFilesManager saveImage:image key:imageTransformPathKey]; NSError * error; UNNotificationAttachment * attachment = [UNNotificationAttachment attachmentWithIdentifier:attachmentIdentifier URL:[RITLPushFilesManager imageUrlPathWithKey:imageTransformPathKey] options:nil error:&error]; NSAssert(error == nil, error.localizedDescription); [attachments addObject:attachment]; return [attachments mutableCopy]; }
預覽圖如下:
推送策略是什麼呢,可以理解為推送的一個”類別”,當我們使用3D Touch得以響應推送信息之後,會出現類似的一排按鈕,不過目前最大的限制為4個,並且最早出於iOS 8.0(那個時候沒有3D Touch感應,怎麼能喚出拓展呢? 如果能告知的小伙伴,也請告知一下樓主,十分感謝)
同樣為了方便管理添加拓展,將添加拓展的方法封裝成RITLPushCategoryManager類
// 為Demo添加默認的策略--before iOS10 +(UIUserNotificationCategory *)addDefaultCategorysBeforeiOS10 { //設置普通響應 -- 表示沒有便利初始化方法很坑 UIMutableUserNotificationAction * foregroundAction = [UIMutableUserNotificationAction new]; //設置屬性 foregroundAction.identifier = foregroundActionIdentifier; foregroundAction.title = @"收到了"; foregroundAction.activationMode = UIUserNotificationActivationModeForeground; //設置文本響應 UIMutableUserNotificationAction * destructiveTextAction = [UIMutableUserNotificationAction new]; //設置屬性 destructiveTextAction.identifier = destructiveTextActionIdentifier; destructiveTextAction.title = @"我想說兩句"; destructiveTextAction.activationMode = UIUserNotificationActivationModeForeground; destructiveTextAction.behavior = UIUserNotificationActionBehaviorTextInput; destructiveTextAction.authenticationRequired = false; destructiveTextAction.destructive = true; //初始化Category UIMutableUserNotificationCategory * category = [UIMutableUserNotificationCategory new]; //設置屬性 category.identifier = RITLRequestIdentifier; [category setActions:@[foregroundAction,destructiveTextAction] forContext:UIUserNotificationActionContextDefault]; //返回 return [category copy]; } //並在外部使用注冊推送的時候添加即可,代碼有點長,Demo中有演示 /* [[UIApplication sharedApplication] registerUserNotificationSettings:categories:中的第二個參數,以NSSet的形式傳入即可 */
UserNotifications框架為我們提供了很多的便利初始化方法,從代碼也可以看出它的簡潔性,由於是單行,所以會顯得比較長 (相信我,在這裡換行格式也是很難看的,所以索性用了一行 0.0)
+(void)addDefaultCategorys { // 設置響應 UNNotificationAction * foregroundAction = [UNNotificationAction actionWithIdentifier:foregroundActionIdentifier title:@"收到了" options:UNNotificationActionOptionForeground]; // 設置文本響應 UNTextInputNotificationAction * destructiveTextAction = [UNTextInputNotificationAction actionWithIdentifier:destructiveTextActionIdentifier title:@"我想說兩句" options:UNNotificationActionOptionDestructive|UNNotificationActionOptionForeground textInputButtonTitle:@"發送" textInputPlaceholder:@"想說什麼?"]; // 初始化策略對象,這裡的categoryWithIdentifier一定要與需要使用Category的UNNotificationRequest的identifier匹配(相同)才可觸發 UNNotificationCategory * category = [UNNotificationCategory categoryWithIdentifier:RITLRequestIdentifier actions:@[foregroundAction,destructiveTextAction] intentIdentifiers:@[foregroundActionIdentifier,destructiveTextActionIdentifier] options:UNNotificationCategoryOptionCustomDismissAction]; //直接通過UNUserNotificationCenter設置策略即可 [[UNUserNotificationCenter currentNotificationCenter]setNotificationCategories:[NSSet setWithObjects:category, nil]]; }
如何響應我們添加的策略呢,這裡就只介紹UserNotifications下的響應方法,找到負責響應最新推送協議方法的類別RITLOriginPushAppDelegate+RITLUserNotifications:
在- (void)userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:方法體最前面進行一下策略判定即可,如下:
if ([response.actionIdentifier isEqualToString:foregroundActionIdentifier]) { //可以彈出Alert提示一下 [self performSelector:NSSelectorFromString(@"__showAlert:") withObject:@"我是第一個策略動作,收到了" afterDelay:0]; completionHandler();return; } else if([response.actionIdentifier isEqualToString:destructiveTextActionIdentifier]) { [self performSelector:NSSelectorFromString(@"__showAlert:") withObject:[NSString stringWithFormat:@"我是第二個文本動作,我輸入的文字是:%@",((UNTextInputNotificationResponse *)response).userText] afterDelay:0]; completionHandler();return; }
下面是通過Touch喚起推送策略、響應text策略以及響應策略的預覽圖
與Widget插件化開發的創建步驟是一樣的呢,File->New->Target->NotificationContentExtension
創建成功之後,默認的控制器名稱為NotificationViewController,Demo中僅僅改了一下名字,文件夾分布如下:
如果牽扯到UI的繪制的方法,數據與代碼的共享的方法,作為插件化開發其實是一致的,可回顧一下博主之前的博文iOS開發——Widget(Today Extension)插件化開發感謝。
這裡需要注意一下,如果我們創建了拓展,但是本地推送的UI如果還是默認的UI形式,這個時候就需要看一下Info.plist文件下 NSExtension->NSExtensionAttributes->UNNotificationExtensionCategory (默認是一個String類型),裡面需要與UNNotificationRequest對象的identifier相匹配才可觸發;如果支持多個通知,可以將UNNotificationExtensionCategory更改為數組類型。下面是一個栗子0.0
下面是Demo中進行本地推送中初始化UNNotificationRequest對象的具體代碼形式:
//作為一個全局的固定字符串 NSString * const RITLRequestIdentifier = @"com.yue.originPush.myNotificationCategory"; //初始化通知請求 UNNotificationRequest * request = [UNNotificationRequest requestWithIdentifier:RITLRequestIdentifier content:content trigger:trigger];
同時為了保證能夠觸發自定義的推送UI,Demo中的plist文件設置如下:
在Demo中,樓主依舊使用了storyboard進行UI布局,也只因為是研究框架,所以布局是非常的簡單,如下:
這個協議也是比較簡單的,只有兩個協議方法,有一個必須實現的方法,也有一個可選的。
// 收到推送消息後進行的回調,必須實現的方法 - (void)didReceiveNotification:(UNNotification *)notification { //獲得內容對象 UNNotificationContent * content = notification.request.content; //獲得需要展示的文本 NSString * customTitle = content.body; //需要展示的圖片 UIImage * image = [UIImage imageNamed:content.launchImageName]; //設置 self.customlabel.text = customTitle; //這是拓展裡自定義的圖片 self.customimageView.image = image; //這是通知裡帶的照片 self.attachmentImageView.image = nil;//直接使用attachment對象的路徑進行加載即可 //如果是遠程推送的網絡圖沒有加載怎麼辦,這裡不用擔心 //下面的NotificationServiceExtension就是解決這個問題的 }
下面這個協議方法是可選的。
它的作用就是,當我們使用自定義的UI進行通知顯示的時候,通過點擊或者響應策略Action的時候,會優先執行該協議方法,並通過它的回調來決定下一步的操作。
//回調類型的個人理解如下: typedef NS_ENUM(NSUInteger, UNNotificationContentExtensionResponseOption) { UNNotificationContentExtensionResponseOptionDoNotDismiss, //默認表示不消失 UNNotificationContentExtensionResponseOptionDismiss,//消失 UNNotificationContentExtensionResponseOptionDismissAndForwardAction,//消失並讓App對它進行處理,這個時候才會走原應用的回調 };
// 展開後的推送消息得到點擊響應 - (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption option))completion { //進行回調,這裡是使其消失並回到主App進行處理,處理完畢之後會走UNUserNotificationCenter的協議方法 completion(UNNotificationContentExtensionResponseOptionDismissAndForwardAction); }
下面是使用自定義的通知UI、使用策略輸入文本以及最後響應文本的操作
如果眼睛比較厲害的小伙伴估計上面的截圖也看到了,在NotificationContentExtension旁邊,如下圖:
這個插件的作用是什麼呢,當然這個插件主要是用於遠程推送的數據處理,它能夠給我們最長30秒的時間讓我們對遠程推送的內容進行修改,或者對推送內容中的圖片、視頻、音頻鏈接進行下載的過程。
當然大部分的代碼系統已經幫我們寫好了,這裡之貼上Demo中的一個小實現,作用就是在收到遠程推送的時候,修改推送的內容,如下:
//大約會給30秒的時間限制 - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { //獲取request以及block對象 self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; //對內容可以進行修改 self.bestAttemptContent.body = @"我是在Service裡面修改後的title"; //如果如果含有圖片,視頻音頻的url,可以利用這裡進行下載coding... //然後初始化UNNotificationAttachment對象,賦值數組即可 //回調處理完畢的content內容 self.contentHandler(self.bestAttemptContent); }
下面的協議方法雖然能大體翻譯出來,但卻不知道到底有什麼用,如果有知道的小伙伴,也請告知一下,十分感謝
//提供最後一個機會,當該拓展將被系統殺死的時候執行的方法 - (void)serviceExtensionTimeWillExpire { // Called just before the extension will be terminated by the system. // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. //就比如上面英文介紹所說的:可以用這個機會來表達一下你最想在content中表達的,不然的話最初推送的payload將被用到 self.contentHandler(self.bestAttemptContent); }
使用pushMeBody進行一次遠程推送,Touch響應以及點擊推送該內容結果如下:
更多的請在GitHub