iOS 10 UserNotification框架解析 - 本地通知

iOS 10以前的通知比較雜亂,把本地通知和遠程通知分開了,誕生了許多功能類似的API,很容易讓初學者犯迷糊。而iOS 10的通知把API做了統一,利用獨立的UserNotifications.framework框架來管理通知;並且,還增加了撤銷單條通知、更新已展示通知、中途修改通知內容等等,以及在通知中展示圖片視頻,自定義通知UI等一系列新功能;總之,iOS 10的通知功能十分強大。

瞭解通知之前,有必要了解一下通知的歷史現狀。由於通知可以方便的提示用戶應用的狀態、傳遞重要的信息,所以自從iOS 3引入通知以來,幾乎每個新的版本,Apple都會增強通知的功能。

一、發展歷程:

iOS 3 - 引入推送通知

UIApplication 的 registerForRemoteNotificationTypesUIApplicationDelegateapplication(_:didRegisterForRemoteNotificationsWithDeviceToken:)application(_:didReceiveRemoteNotification:)

iOS 4 - 引入本地通知

scheduleLocalNotificationpresentLocalNotificationNow:application(_:didReceive:)

iOS 5 - 加入通知中心頁面

iOS 6 - 通知中心頁面與 iCloud 同步

iOS 7 - 後臺靜默推送

application(_:didReceiveRemoteNotification:fetchCompletionHandle:)

iOS 8 - 重新設計notification權限請求,加入交互式通知

Actionable 通知 registerUserNotificationSettings(_:),UIUserNotificationActionUIUserNotificationCategoryapplication(_:handleActionWithIdentifier:forRemoteNotification:completionHandler:)

iOS 9 - Text Input action

基於 HTTP/2 的推送請求 UIUserNotificationActionBehavior,全新的 Provider API 等

二、通知應用

申請權限

    // 獲取通知中心對象
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

    // 申請通知權限
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (granted) {
            NSLog(@"通知開啓");
        } else {
            NSLog(@"關閉通知");
        }
    }];

    // 獲取授權的通知權限
    [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        NSLog(@"%@", settings);
    }];

requestAuthorizationWithOptions:

申請通知的權限,iOS 10不再區分遠程通知和本地通知的權限申請,統一用該方法做權限申請

添加通知

    // 創建通知對象
    UNMutableNotificationContent *noticeContent = [[UNMutableNotificationContent alloc] init]];
    // 設置通知標題
    noticeContent.title = @"iOS10通知";
    // 設置通知子標題
    noticeContent.subtitle = @"新通知學習筆記";
    // 設置通知內容
    noticeContent.body = @"新通知變化很大,之前本地通知和遠程推送是兩個類,現在合成一個了。";
    // 添加通知的聲音
    UNNotificationSound *sound = [UNNotificationSound soundNamed:@"caodi.m4a"];
    noticeContent.sound = sound;

UNMutableNotificationContent

通知的內容,可以設置通知的標題、副標題、具體內容,以及通知的圖片、視頻、聲音和交互信息等等

UNNotificationSound

應用在後臺時收到通知時的提示音

觸發機制

    // 如果repeats爲YES,那麼triggerWithTimeInterval的值要大於60s
    UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:3 repeats:NO];

    NSString *requestIdentifier = @"requestIdentifier";

    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier content:content trigger:trigger1];

UNTimeIntervalNotificationTrigger

設置通知觸發的條件,分爲以下幾類:

  • 1.UNPushNotificaitonTrigger

推送服務的Trigger,由系統創建

  • 2.UNTimeIntervalNotificaitonTrigger

時間觸發器,可以設置多長時間後觸發通知,repeats參數爲是否重複觸發,如果設置YES,那麼triggerWithTimeInterval的時間必須大於60s

  • 3.UNCalendarNotificaitonTrigger

日期觸發器,可以設置特定日期觸發

  • 4.UNLocationNotificaitonTrigger

位置觸發器,用於到達特定位置後才觸發通知,需要設置CLRegion的具體區域

發送通知

    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
        NSLog(@"發送通知出錯: %@", error);
    }];

addNotificationRequest:withCompletionHandler:

把通知添加到通知中心,就可以發送通知了

擴展通知

我們可以在通知中添加聲音、圖片和視頻,來豐富通知的內容,在支持3D-touch的手機上,重壓之後會全面顯示;另外,我們也可以添加交互式通知,進一步提高用戶體驗

文件大小

UNNotificationationAttachment

通知的附近,我們可以在附近中添加圖片、音頻或視頻。

添加圖片

    UNMutableNotificationContent *noticeContent = [[UNMutableNotificationContent alloc] init];

    NSString *imageFile = [[NSBundle mainBundle] pathForResource:@"sport" ofType:@"png"];
    UNNotificationAttachment *imageAttachment = [UNNotificationAttachment attachmentWithIdentifier:@"imageAttachment" URL:[NSURL fileURLWithPath:imageFile] options:nil error:nil];
    NSAssert(imageAttachment != nil, @"imageAttach 不能爲空");
    noticeContent.attachments = @[imageAttachment];

添加視頻

    UNMutableNotificationContent *noticeContent = [[UNMutableNotificationContent alloc] init];

    NSString *movieFile = [[NSBundle mainBundle] pathForResource:@"movie" ofType:@"mp4"];
    UNNotificationAttachment *movieAttachment = [UNNotificationAttachment attachmentWithIdentifier:@"movieAttachment" URL:[NSURL fileURLWithPath:movieFile] options:nil error:nil];
    NSAssert(movieAttachment != nil, @"movieAttach 不能爲空");
    noticeContent.attachments = @[movieAttachment];

添加交互式通知

添加交互式通知

    UNMutableNotificationContent *noticeContent = [[UNMutableNotificationContent alloc] init];

    // 文字action
    UNTextInputNotificationAction *action1 = [UNTextInputNotificationAction actionWithIdentifier:@"replyAction" title:@"文字回覆" options:UNNotificationActionOptionNone];
    // 進入應用action
    UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:@"enterAction" title:@"進入應用" options:UNNotificationActionOptionForeground];
    // 取消action
    UNNotificationAction *action3 = [UNNotificationAction actionWithIdentifier:@"cancelAction" title:@"取消" options:UNNotificationActionOptionDestructive];

    UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:@"Categroy" actions:@[action1, action2, action3] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];

    [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObject:category]];

    noticeContent.categoryIdentifier = @"Categroy";

獲取交互動作

    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler
{
    NSString *categoryIdentifier = response.notification.request.content.categoryIdentifier;

    if ([categoryIdentifier isEqualToString:@"Categroy"]) {
        if ([response.actionIdentifier isEqualToString:@"replyAction"]) {
            UNTextInputNotificationResponse *textResponse = (UNTextInputNotificationResponse*)response;

            NSString *userText = textResponse.userText;

            NSLog(@"您輸入的內容:%@", userText);

        } else if ([response.actionIdentifier isEqualToString:@"enterAction"]) {
            NSLog(@"點擊進入了應用");
        } else {
            NSLog(@"點擊了取消");
        }
    }

    completionHandler();
}

iOS 10把接收通知的方法做了統一,不再區分接收本地和遠程的通知,只分前臺和後臺時受到的通知。

接收通知的步驟:

1.設置通知的代理,一般設置在AppDelegate

[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];

2.實現代理方法

    // 應用在前臺收到通知的處理方法
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler

    // 應用在後臺收到通知的處理方法
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler

自定義通知樣式

iOS 10可以設置通知的UI樣式,更加方便給用戶定製化。必須用iPhone7或iPhone7 Plus,iPhone6s及以下硬件,即使升級到iOS 10也無法顯示自定義通知的樣式

1.創建自定義通知UI文件,在XcodeFile->New->Targe會出現下面的視圖

圖1

其中,與通知相關的擴展有兩個:Notification ContentNotification Service Extension,前者是自定義通知的類型,後者是我們收到遠程通知後,在展示之前對通知的修改。所以,我們採用前者

2.修改通知視圖的控制器,自定義通知樣式

  • NotificationViewController文件:

- (void)didReceiveNotification:(UNNotification *)notification可以設置UI顯示的數據

  • MainInterface.storyboard文件

我們可以通過這個storyboard來具體定製通知的樣式

3.應用自定義通知樣式

修改NotificationViewControllerinfo.plist文件

圖2

  • UNNotificationExtensionCategory

UNNotificationCategory的標識,需要設置爲我們的通知的標識

  • UNNotificationExtensionInitialContentSizeRatio

通知內容顯示的比例大小,默認爲1

  • UNNotificationExtensionDefaultContentHidden

是否隱藏默認通知,設置爲YES後,默認通知會隱藏

移除通知

[[UNUserNotificationCenter currentNotificationCenter] removePendingNotificationRequestsWithIdentifiers:@[@"requestIdentifier"]];

至此,iOS 10本地通知已經解析完畢,下一篇是遠程通知,……

實例項目

https://github.com/BirdandLion/UNNotificationDemo.git

參考資料

https://developer.apple.com/reference/usernotifications

https://onevcat.com/2016/08/notification/

http://www.jianshu.com/p/5713fa2bfece

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章