玩轉 iOS 10 推送 —— UserNotifications Framework(上)

pikacode發表於2019-02-19

iOS 10 came

在今年 6月14號 蘋果開發者大會 WWDC 2016 之後,筆者趕緊就去 apple 的開發者網站下載了最新的 Xcode 8 betaiOS 10 beta,然後在自己的手機上裝了 iOS 10 beta ,狠狠地體驗了一把。
可以說 iOS 10 無論從介面風格,還是 Framework 都做了很多改動。最直觀的感受就是介面的圓角增多了,系統動畫更加多樣和流暢,系統 App 的功能也變得更豐富了。

而 iOS 10 裡的推送功能,也較之前更加強大,
今天我們就來聊聊 iOS 10 裡的推送功能。

Notifications before iOS 10

首先我們一起簡單回顧下 iOS 10 以前的推送服務。
iOS 推送分為 Local Notifications(本地推送) 和 Remote Notifications(遠端推送),先看 2 張圖:

玩轉 iOS 10 推送 —— UserNotifications Framework(上)
Local Notifications

玩轉 iOS 10 推送 —— UserNotifications Framework(上)
Remote Notifications

簡單的說就是本地推送通過 App 本地定製,加入到系統的 Schedule 裡,然後在指定的時間推送指定文字。而遠端推送通過服務端向蘋果推送伺服器 Apple Push Notification Service (APNs) 傳送 Notification Payload,之後 APNs 再將推送下發到指定裝置的 指定 App 上。
以及 iOS 7 之後在不顯式地彈窗打擾使用者的情況下,進行的靜默推送

玩轉 iOS 10 推送 —— UserNotifications Framework(上)
Silent Push

具體做法可以參考 iOS 7 Background Remote Notification

User Notifications Framework


好,扯了這麼多,該進入今天的正題了 —— User Notifications Framework 。
首先在 AppDelegate.m

import
#import <UserNotifications/UserNotifications.h>複製程式碼
註冊推送

以下分別是 iOS 10 之前和之後的註冊方式,其中的 UNAuthorizationOptions 裡還可以找到 1 個 UNAuthorizationOptionCarPlay 的值是專為車載系統定製的值。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    //iOS 10 before
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [application registerUserNotificationSettings:settings];

    //iOS 10
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (!error) {
            NSLog(@"request authorization succeeded!");
        }
    }];

    return YES;
}複製程式碼
Notification settings

之前註冊推送服務,ios 8 及之前使用了不同的 API,並且返回結果也不同。現在 apple 不僅統一了這個 API,而且我們可以獲取到使用者更加詳細的設定了。

[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        NSLog(@"%@",settings);
}];複製程式碼

列印獲得如下資訊:

<UNNotificationSettings: 0x16567310; 
authorizationStatus: Authorized, 
notificationCenterSetting: Enabled, 
soundSetting: Enabled, 
badgeSetting: Enabled, 
lockScreenSetting: Enabled, 
alertSetting: NotSupported,
carPlaySetting: Enabled, 
alertStyle: Banner>複製程式碼
Token Registration

跟之前一樣

[[UIApplication sharedApplication] registerForRemoteNotifications];複製程式碼
Content

以前只能展示一條文字,現在可以有 title 、subtitle 以及 body 了。

玩轉 iOS 10 推送 —— UserNotifications Framework(上)

定製方法如下:

//Local Notification
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = @"Introduction to Notifications";
content.subtitle = @"Session 707";
content.body = @"Woah! These new notifications look amazing! Don’t you agree?";
content.badge = @1;

//Remote Notification
{
"aps" : {
    "alert" : { 
         "title" : "Introduction to Notifications", 
         "subtitle" : "Session 707",         
         "body" : "Woah! These new notifications look amazing! Don’t you agree?"
                },
    "badge" : 1
        },
}複製程式碼
Triggers

又是一個新的功能,有三種

  • UNTimeIntervalNotificationTrigger
  • UNCalendarNotificationTrigger
  • UNLocationNotificationTrigger
//2 分鐘後提醒
UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:120 repeats:NO];

//每小時重複 1 次喊我喝水
UNTimeIntervalNotificationTrigger *trigger2 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:3600 repeats:YES];

//每週一早上 8:00 提醒我給老婆做早飯
NSDateComponents *components = [[NSDateComponents alloc] init];
components.weekday = 2;
components.hour = 8;
UNCalendarNotificationTrigger *trigger3 = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];

//#import <CoreLocation/CoreLocation.h>
//一到麥當勞就喊我下車
CLRegion *region = [[CLRegion alloc] init];
UNLocationNotificationTrigger *trigger4 = [UNLocationNotificationTrigger triggerWithRegion:region repeats:NO];複製程式碼
Add Request
NSString *requestIdentifier = @"sampleRequest";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier
                                                                          content:content
                                                                          trigger:trigger1];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {

}];複製程式碼

推送小結

然後整個推送的過程就變成了醬紫:

玩轉 iOS 10 推送 —— UserNotifications Framework(上)
  • Local Notifications 通過定義 ContentTriggerUNUserNotificationCenter 進行 request 這三部曲來實現。
  • Remote Notifications 則向 APNs 傳送 Notification Payload
Notification Handling

設定了推送,然後就結束了?iOS 10 並沒有這麼簡單!
通過實現協議,使 App 處於前臺時捕捉並處理即將觸發的推送:

@interface AppDelegate () <UNUserNotificationCenterDelegate>

-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{

    completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound);

}複製程式碼

讓它只顯示 alert 和 sound ,而忽略 badge 。

Notification Management

徹底掌控整個推送週期:

  • Local Notification 通過更新 request
  • Remote Notification 通過新的欄位 apns-collapse-id

通過之前的 addNotificationRequest: 方法,在 id 不變的情況下重新新增,就可以重新整理原有的推送。

NSString *requestIdentifier = @"sampleRequest";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier
                                                                      content:newContent
                                                                      trigger:newTrigger1];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {

}];複製程式碼

刪除計劃的推送:

[center removePendingNotificationRequestsWithIdentifiers:@[requestIdentifier]];複製程式碼

此外 UNUserNotificationCenter.h 中還有諸如刪除所有推送、檢視已經發出的推送、刪除已經發出的推送等等強大的介面。

重新整理原有的推送後,在通知中心的顯示裡,也會有相應的變化,這裡注意第 2 條資訊,現在比分是 1:0

玩轉 iOS 10 推送 —— UserNotifications Framework(上)

比分重新整理後為 1:1,在不產生新的推送條目的情況下位置被前置了!

玩轉 iOS 10 推送 —— UserNotifications Framework(上)

試想利用這個方法,不斷的重新整理推送,是不是就可以做到讓自己 App 的推送內容始終展示在使用者手機通知中心的最頂端,力壓其餘所有內容了呢?總感覺有點不厚道啊~

Advanced Notifications


關於推送的更多類似 Media Attachments 的高階功能,我們將在下一篇裡詳細討論。

Media Attachments

為推送新增更多媒體附件,諸如圖片、音樂

玩轉 iOS 10 推送 —— UserNotifications Framework(上)

繼續瀏覽下一篇 玩轉 iOS 10 推送 (中)


相關文章