iOS 10 came
在今年 6月14號 蘋果開發者大會 WWDC 2016 之後,筆者趕緊就去 apple 的開發者網站下載了最新的 Xcode 8 beta 和 iOS 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 張圖:
簡單的說就是本地推送通過 App 本地定製,加入到系統的 Schedule 裡,然後在指定的時間推送指定文字。而遠端推送通過服務端向蘋果推送伺服器 Apple Push Notification Service (APNs) 傳送 Notification Payload,之後 APNs 再將推送下發到指定裝置的 指定 App 上。
以及 iOS 7 之後在不顯式地彈窗打擾使用者的情況下,進行的靜默推送:
具體做法可以參考 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 了。
定製方法如下:
//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) {
}];複製程式碼
推送小結
然後整個推送的過程就變成了醬紫:
- 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
比分重新整理後為 1:1,在不產生新的推送條目的情況下位置被前置了!
試想利用這個方法,不斷的重新整理推送,是不是就可以做到讓自己 App 的推送內容始終展示在使用者手機通知中心的最頂端,力壓其餘所有內容了呢?總感覺有點不厚道啊~
Advanced Notifications
關於推送的更多類似 Media Attachments
的高階功能,我們將在下一篇裡詳細討論。
Media Attachments
為推送新增更多媒體附件,諸如圖片、音樂