iOS 10前后兩種本地通知

通知大家都不陌生,其實通知分兩種,遠程通知和本地通知。

遠程通知是指服務器發出的通知,通過蘋果的推送然后到達用戶設備。本地通知是指不通過網絡,直接安裝應用后就可以接到通知了,典型的例子是日歷、待辦、鬧鐘等應用。

不過就表現形式來說兩者基本一樣,都會出現在通知中心,都可以出現在鎖屏界面,都可以出現在界面上部,都可以添加應用上的紅點。

image.png
image.png

這里我定時不斷發送通知,每次收到通知都添加到列表中,點擊列表可以復制通知內容。

對于本地通知,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;//收到通知時播放的聲音,默認消息聲音
//    notification.soundName=@"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的手機上測試收不到通知,不知道是不是在新系統必須要用新的庫。

沒什么好結的,以上。


示例工程:https://github.com/Cloudox/OXNotificationTest
查看作者首頁

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容