iOS 10 的推送 User Notifications Framework

皮皮醬發表於2018-10-30

介紹

User Notifications Framework 是蘋果在 WWDC 2016 推出的。iOS 10 中以前雜亂的和通知相關的 API 都被統一了,現在開發者可以使用獨立的 UserNotifications.framework 來集中管理和使用 iOS 系統中通知的功能。在此基礎上,Apple 還增加了撤回單條通知,更新已展示通知,中途修改通知內容,在通知中展示圖片視訊,自定義通知 UI 等一系列新功能,非常強大。

iOS 10 以前的推送

iOS 10 以前推送分為 Local Notifications(本地推送) 和 Remote Notifications(遠端推送)。

本地推送:通過 App 本地定製,加入到系統的 Schedule 裡,然後在指定的時間推送指定文字。.

iOS 10 的推送 User Notifications Framework

遠端推送:通過服務端向蘋果推送伺服器 Apple Push Notification Service (APNs) 傳送 Notification Payload,之後 APNs 再將推送下發到指定裝置的 指定 App 上。

iOS 10 的推送 User Notifications Framework

User Notifications Framework

基本配置

如果只是簡單的本地推送,跳過 1 、2 步驟,直接到步驟 3。

1、 如果你的 App 有遠端推送的話,那你需要開發者賬號的,需要新建一個對應你 bundle 的 push 證書。 具體的證書製作請參考這裡
2、 Capabilities 中開啟 Push Notifications 開關在 XCode7 中這裡的開關不開啟,推送也是可以正常使用的,但是在 XCode8 中,這裡的開關必須要開啟,不然會報錯:

Error Domain=NSCocoaErrorDomain Code=3000 "未找到應用程式的“aps-environment”的授權字串" UserInfo={NSLocalizedDescription=未找到應用程式的“aps-environment”的授權字串}
複製程式碼

iOS 10 的推送 User Notifications Framework

許可權申請

在使用 UserNotifications 框架的 API 的時候,首先要匯入 UserNotifications 框架:

#import <UserNotifications/UserNotifications.h>
複製程式碼

註冊推送

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if (!error)
        {
            NSLog(@"請求授權成功");
        }
        else
        {
            NSLog(@"請求授權失敗");
        }
}];
複製程式碼

Notification settings:之前註冊推送服務,使用者點選了同意還是不同意,以及使用者之後又做了怎樣的更改我們都無從得知,現在 apple 開放了這個 API,我們可以直接獲取到使用者的設定資訊了。注意 UNNotificationSettings 是隻讀物件哦,不能直接修改!只能通過以下方式獲取

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

列印

<UNNotificationSettings: 0x6000022f9dc0; 
authorizationStatus: NotDetermined, 
notificationCenterSetting: NotSupported, 
soundSetting: NotSupported, 
badgeSetting: NotSupported, 
lockScreenSetting: NotSupported, 
carPlaySetting: NotSupported, 
criticalAlertSetting: NotSupported, 
alertSetting: NotSupported, 
alertStyle: None, 
providesAppNotificationSettings: No>
複製程式碼

Token Registration

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

獲取裝置的Device Token

//獲取DeviceToken成功
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSString *deviceString = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    deviceString = [deviceString stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"deviceToken:%@",deviceString);
}

//獲取DeviceToken失敗
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"[DeviceToken Error]:%@\n",error.description);
}
複製程式碼

接收推送的代理方法

// App處於前臺接收通知時
// 只有app處於前臺狀態下才會呼叫,後臺狀態或者應用殺死下是不會呼叫這個方法的
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler 

// App通知的點選事件
// 使用者點選訊息才會觸發
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler 
複製程式碼

蘋果把本地通知跟遠端通知合二為一。區分本地通知跟遠端通知的類是UNPushNotificationTrigger.h 類中,UNPushNotificationTrigger 的型別是新增加的。

UNPushNotificationTrigger (遠端通知) 遠端推送的通知型別
UNTimeIntervalNotificationTrigger (本地通知) 一定時間之後,重複或者不重複推送通知。我們可以設定timeInterval(時間間隔)和repeats(是否重複)。
UNCalendarNotificationTrigger(本地通知) 一定日期之後,重複或者不重複推送通知 例如,你每天8點推送一個通知,只要dateComponents為8,如果你想每天8點都推送這個通知,只要repeats為YES就可以了。
UNLocationNotificationTrigger (本地通知)地理位置的一種通知,
當使用者進入或離開一個地理區域來通知。

內容

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

iOS 10 的推送 User Notifications Framework

定製方法如下:

//本地通知
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = @"CALENDAR";
content.subtitle = @"Lunch";
content.body = @"Today at 12:00 PM";
content.badge = @1;

//遠端推送
{
"aps" : {
    "alert" : { 
         "title" : "CALENDAR", 
         "subtitle" : "Lunch",         
         "body" : "Today at 12:00 PM"
                },
    "badge" : 1
        },
}
複製程式碼

Triggers

UNTimeIntervalNotificationTrigger 定時推送
UNCalendarNotificationTrigger 定期推送
UNLocationNotificationTrigger 定點推送

//60 秒後提醒
//timeInterval:單位為秒(s)  repeats:是否迴圈提醒
UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:60 repeats:NO];

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

//首先得匯入#import <CoreLocation/CoreLocation.h>,不然會regin建立有問題。
CLLocationCoordinate2D center1 = CLLocationCoordinate2DMake(31.234567, 117.4567890);
  CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center1 radius:500 identifier:@"桂林路"];
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 的推送 User Notifications Framework

Local Notifications 通過定義 Content 和 Trigger 向 UNUserNotificationCenter 進行 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 的推送 User Notifications Framework

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

iOS 10 的推送 User Notifications Framework

上面簡單介紹了 iOS 10 的新框架 User Notifications Framework,瞭解完 iOS 10 的框架之後,還要適配iOS 8 9 系統,是不是覺得很麻煩,筆者最近發現了一款 SDK ---- MobPush,相容 iOS 8-12 系統,接入非常簡單,3行程式碼就可以搞定推送。

MPushNotificationConfiguration *configuration = [[MPushNotificationConfiguration alloc] init];
configuration.types = MPushAuthorizationOptionsBadge | MPushAuthorizationOptionsSound | MPushAuthorizationOptionsAlert;
[MobPush setupNotification:configuration];
複製程式碼

同時,MobPush 支援多樣化推送場景、使用者分群、AB 測試、智慧推送等等功能,還有完善的資料統計後臺可以從多個維度實時瞭解 APP 和使用者的使用情況,瞭解更多



相關文章