iOS 10前後兩種本地通知
引
通知大家都不陌生,其實通知分兩種,遠端通知和本地通知。
遠端通知是指伺服器發出的通知,通過蘋果的推送然後到達使用者裝置。本地通知是指不通過網路,直接安裝應用後就可以接到通知了,典型的例子是日曆、待辦、鬧鐘等應用。
不過就表現形式來說兩者基本一樣,都會出現在通知中心,都可以出現在鎖屏介面,都可以出現在介面上部,都可以新增應用上的紅點。
這裡我定時不斷髮送通知,每次收到通知都新增到列表中,點選列表可以複製通知內容。
對於本地通知,iOS 10以前和以後分兩種實現方式,這裡都放出來。
需要注意的是,現在在Xcode中使用遠端通知功能需要在工程的Targets中的Capabilities標籤裡開啟Push Notification許可權,且需要APNS證書,不過本地通知是不需要的,可以直接測試接收通知。
iOS 10以上系統的實現
iOS 10以前使用UILocalNotification,iOS開始支援一個新的類庫UNUserNotificationCenter,都給了他特定的字首UN了,可見重視程度。
如上面第一張圖所示,要發通知是需要使用者同意的,也就是在第一次開啟App的時候必須嘗試註冊通知,如果不註冊,那麼即使使用者去設定中找也無法再通知裡找到你的App然後開啟。
所以我們需要在AppDelegate.m的application: didFinishLaunchingWithOptions:方法中註冊通知:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 註冊通知
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
return YES;
}
這樣就會在第一次啟動App時向用戶索取許可權。接下來就可以決定發什麼通知以及收到通知後怎麼處理了。
我們可以定義一個方法來發通知:
#import <UserNotifications/UserNotifications.h>
……
/**
iOS 10以後的本地通知
*/
- (void)addlocalNotificationForNewVersion {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:@"Hello" arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:[NSString stringWithFormat:@"Agent-%d",arc4random()%100] arguments:nil];
content.sound = [UNNotificationSound defaultSound];
// UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:alertTime repeats:NO];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"OXNotification" content:content trigger:nil];
[center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
NSLog(@"成功新增推送");
}];
}
發通知的所有內容就在這裡了,明顯可見content是一個通知體,定義通知的一些內容、聲音等,然後放到request中,新增到通知中心就可以了。中間註釋了一行是用來重複通知的,第一個引數是重複的時間間隔,最小60s,第二個引數是是否重複。因為60s太長了不便於測試,所以不如在外部寫一個定時器,重複呼叫這個方法就可以了。
要接收通知並處理必須要遵循 UNUserNotificationCenterDelegate 這個協議,上面程式碼中就設定了delegate是self,然後就可以處理接收通知:
#pragma mark - UNUserNotificationCenterDelegate
// iOS 10收到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
NSDictionary * userInfo = notification.request.content.userInfo;
UNNotificationRequest *request = notification.request; // 收到推送的請求
UNNotificationContent *content = request.content; // 收到推送的訊息內容
NSNumber *badge = content.badge; // 推送訊息的角標
NSString *body = content.body; // 推送訊息體
UNNotificationSound *sound = content.sound; // 推送訊息的聲音
NSString *subtitle = content.subtitle; // 推送訊息的副標題
NSString *title = content.title; // 推送訊息的標題
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"iOS10 前臺收到遠端通知:%@", body);
} else {
// 判斷為本地通知
NSLog(@"iOS10 前臺收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
[self.dataArray addObject:content];
[self.timeArray addObject:[self convertNSDateToNSString:[NSDate date]]];
[self.tableView reloadData];
}
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要執行這個方法,選擇是否提醒使用者,有Badge、Sound、Alert三種類型可以設定
}
我這邊的處理是新增到陣列中,並且記錄通知的時間,好在列表中顯示,至於列表怎麼顯示就不寫在這了,需要的同學可以直接看工程程式碼。
關於iOS 10的通知流程就是這些了。
iOS 10以前系統的實現
老系統的實現其實要素都差不多,只不過提供的類庫不一樣,一樣需要在應用一開始的時候註冊通知:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 註冊通知,如果已經獲得傳送通知的授權則建立本地通知,否則請求授權(注意:如果不請求授權在設定中是沒有對應的通知設定項的,也就是說如果從來沒有傳送過請求,即使通過設定也打不開訊息允許設定)
if ([[UIApplication sharedApplication] currentUserNotificationSettings].types != UIUserNotificationTypeNone) {
[self addLocalNotificationForOldVersion];
} else {
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
return YES;
}
新增通知我們也放到一個方法中:
/**
iOS 10以前版本新增本地通知
*/
- (void)addLocalNotificationForOldVersion {
//定義本地通知物件
UILocalNotification *notification = [[UILocalNotification alloc] init];
//設定呼叫時間
notification.timeZone = [NSTimeZone localTimeZone];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:2.0];//通知觸發的時間,10s以後
notification.repeatInterval = 2;//通知重複次數
notification.repeatCalendar=[NSCalendar currentCalendar];//當前日曆,使用前最好設定時區等資訊以便能夠自動同步時間
//設定通知屬性
notification.alertBody = [NSString stringWithFormat:@"Agent-%d",arc4random()%100]; //通知主體
notification.applicationIconBadgeNumber += 1;//應用程式圖示右上角顯示的訊息數
notification.alertAction = @"開啟應用"; //待機介面的滑動動作提示
notification.alertLaunchImage = @"Default";//通過點選通知開啟應用時的啟動圖片,這裡使用程式啟動圖片
notification.soundName = UILocalNotificationDefaultSoundName;//收到通知時播放的聲音,預設訊息聲音
// [email protected]"msg.caf";//通知聲音(需要真機才能聽到聲音)
//設定使用者資訊
notification.userInfo = @{@"id": @1, @"user": @"cloudox"};//繫結到通知上的其他附加資訊
//呼叫通知
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
可以看到能夠設定的東西還是蠻多的。
此外還有幾個可能用得到的代理方法:
/**
應用註冊通知後
@param application 應用
@param notificationSettings 通知設定
*/
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
if (notificationSettings.types != UIUserNotificationTypeNone) {
[self addLocalNotificationForOldVersion];
}
}
/**
應用進入前臺時呼叫
@param application 應用
*/
- (void)applicationWillEnterForeground:(UIApplication *)application {
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];//進入前臺取消應用訊息圖示
}
/**
收到通知後回撥
@param application 應用
@param notification 通知
*/
- (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification {
NSLog(@"%@", notification.alertBody);
}
不過我用這個老方法在iOS 10的手機上測試收不到通知,不知道是不是在新系統必須要用新的庫。
結
沒什麼好結的,以上。