iOS 本地通知(未完待續)

西門吹霧發表於2018-01-03

本地通知常用來作為本地提醒,提醒使用者待辦事項,事物提醒,位置提示等功能 iOS 10.0前,本地通知通知使用的是UILocalNotification,10.0後,蘋果推送了專門使用者通知提醒的庫UserNotificaiton.framework

1.使用 UILocalNotification

iOS8.0之前,通知許可權預設開啟,可直接使用,但是之後想要使用通知功能,必須提示使用者開啟通知許可權,所以首先需要註冊通知, 在didFinishLaunchingWithOptions

if ([[UIDevice currentDevice].systemVersion  doubleValue]>=8.0) {
        // iOS8以後 本地通知必須註冊(獲取許可權)
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
        
        [application registerUserNotificationSettings:settings];
        
        
    }
複製程式碼

接下來我們需要新增通知觸發行為,呼叫本地通知

1.建立本地通知例項

UILocalNotification * localNoty = [[UILocalNotification alloc]init];
複製程式碼

2.本地通知屬性設定

   /*  本地通知觸發時間 */
    localNoty.fireDate =   [NSDate dateWithTimeIntervalSinceNow:4.0];
     /*  通知提示框 */
    localNoty.alertBody = @"提示文字";
    /*  通知提示title  */
    localNoty.alertTitle = @"提示框內容";
    /* 通知提示音 */
    localNoty.soundName = UILocalNotificationDefaultSoundName;
     /* 這裡接到本地通知,badge變為1 */
    localNoty.applicationIconBadgeNumber = 1;
    // 設定額外資訊,appdelegate中收到通知,可以根據不同的通知的額外資訊確定跳轉到不同的介面
    localNoty.userInfo = @{@"notifaication":@"我是一條本地推送"};
複製程式碼

還有其他不常用的屬性,如timeZone時區

repeatInterval 多長時間重複一次:一年,一個世紀,一天..

region區域 : 傳入中心點和半徑就可以設定一個區域(如果進入這個區域或者出來這個區域就發出一個通知)

regionTriggersOnce BOOL 預設為YES, 如果進入這個區域或者出來這個區域 只會發出 一次 通知,以後就不傳送了。

alertAction: 設定鎖屏狀態下本地通知下面的 滑動來 ...字樣 預設為滑動來檢視 hasAction: alertAction的屬性是否生效

alertLaunchImage: 點選通知進入app的過程中顯示圖片,隨便寫,如果設定了(不管設定的是什麼),都會載入app預設的啟動圖

alertTitle: 以前專案名稱所在的位置的文字: 不設定顯示專案名稱, 在通知內容上方 soundName: 有通知時的音效 ,UILocalNotificationDefaultSoundName預設聲音 可以更改這個聲音: 只要將音效匯入到工程中,呼叫localNote.soundName = @"111.waw"

3.呼叫通知

[[UIApplication sharedApplication] scheduleLocalNotification:localNoty];
複製程式碼

通知發起後,我們需要接受本地通知,一般在AppDelegate或者其分類中新增實現方法。 一般通知的接受分為三種: 1.前臺接收 2.後臺未殺死程式進入前臺接收 3.程式已經殺死,點選通知訊息啟動app

針對前兩中情況,app的程式仍在執行狀態,在didReceiveLocalNotification方法中,新增執行程式碼,這裡可以通過applicationapplicationState屬性來判斷當前的執行狀態,一般執行的操作是app前臺執行彈出提示框,後臺執行點選通知進入前臺直接執行。可以通過notification.userInfo來獲取傳送通知的userInfo。 針對第三種情況,需要在didFinishLaunchingWithOptions,程式啟動過程中新增執行方法

 /* launchOptions: 1.點選圖示開啟是空的
     2.應用間跳轉是有值的
     3.殺死的應用接收到本地通知,也是有值的
     雖然說launchOptions有值,但是他們不同的key有值
 */
  if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) { // 如果這個key有值,代表是殺死的程式接收到本地通知跳轉
   
        // 檢視launchOptions內容
        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"本地通知" message:[NSString stringWithFormat:@"%@",launchOptions] delegate:self cancelButtonTitle:@"知道了" otherButtonTitles: nil];
        [alert show];
        NSLog(@"跳轉到指定頁面");
    }
複製程式碼

UIApplicationLaunchOptionsLocalNotificationKey這個屬性是啟動的時候用來判斷啟動來源的,Keys used to access values in the launch options dictionary passed to the application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: methods of the app delegate.

具體說明如下

UIApplicationLaunchOptionsURLKey
// A key indicating that the app was launched so that it could open the specified URL.
UIApplicationLaunchOptionsSourceApplicationKey
// A key indicating that another app requested the launch of your app.
UIApplicationLaunchOptionsRemoteNotificationKey
// A key indicating that a remote notification is available for the app to process.
UIApplicationLaunchOptionsLocalNotificationKey
// A key indicating that the app was launched to handle a local notification.
Deprecated
UIApplicationLaunchOptionsAnnotationKey
// A key indicating that the URL passed to your app contained custom annotation data from the source app.
UIApplicationLaunchOptionsLocationKey
// A key indicating that the app was launched to handle an incoming location event.
UIApplicationLaunchOptionsNewsstandDownloadsKey
// A key indicating that the app was launched to process newly downloaded Newsstand assets.
UIApplicationLaunchOptionsBluetoothCentralsKey
// A key indicating that the app was relaunched to handle Bluetooth-related events.
UIApplicationLaunchOptionsBluetoothPeripheralsKey
// A key indicating that the app should continue actions associated with its Bluetooth peripheral objects.
UIApplicationLaunchOptionsShortcutItemKey
// A key indicating that the app was launched in response to the user selecting a Home screen quick action.
UIApplicationLaunchOptionsUserActivityDictionaryKey
// A key indicating that the data associated with an activity that the user wants to continue.
UIApplicationLaunchOptionsUserActivityTypeKey
// A key indicating the type of user activity that the user wants to continue.
複製程式碼

類似,我們可以用 NSDictionary *remoteUserInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];來處理遠端通知。

需要注意一點,傳送多條通知,app的角標會一直累加,所以在啟動app的時候didFinishLaunchingWithOptions需要將角標清零

 [application setApplicationIconBadgeNumber:0 ];
複製程式碼

2.使用UserNotificaiton.framework

相關文件參照:developer.apple.com/documentati… 1.首先,我們需要將UserNotifications引入工程。 然後在AppDelegate.m匯入庫檔案 #import <UserNotifications/UserNotifications.h> 2.授權應用通知許可權

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

之前註冊推送服務,ios 8 及之前使用了不同的 API,並且返回結果也不同。現在 apple 不僅統一了這個 API,而且我們可以獲取到使用者更加詳細的設定了。

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

列印結果如下: <UNNotificationSettings: 0x60400009cd40; authorizationStatus: Authorized, notificationCenterSetting: Enabled, soundSetting: Enabled, badgeSetting: Enabled, lockScreenSetting: Enabled, carPlaySetting: NotSupported, alertSetting: Enabled, alertStyle: Banner>

如果需要註冊遠端通知:

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

2.傳送本地通知 UserNotificaiton傳送本地通知需要使用UNNotificationRequest類,例項方法如下

+ (instancetype)requestWithIdentifier:(NSString *)identifier content:(UNNotificationContent *)content trigger:(nullable UNNotificationTrigger *)trigger;
複製程式碼

所以我們需要分別設定 UNNotificationContentUNNotificationTrigger並設定一個識別符號。

UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = @"this is Notifications";
    content.subtitle = @"本地通知";
    content.body = @"推送一條本地通知";
    content.badge = @1;
    content.userInfo = @{@"type":@"this is a userNotification"};
複製程式碼

Triggers

又是一個新的功能,有三種

  • UNTimeIntervalNotificationTrigger

  • UNCalendarNotificationTrigger

  • UNLocationNotificationTrigger 他們的使用方式如下:

     //8s後提醒
    UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:8 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>
    //一到距離(123.333, 123.344)點20米就喊我下車
    CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:CLLocationCoordinate2DMake(123.333, 123.344) radius:20 identifier:@"regionidentifier"];
  
    UNLocationNotificationTrigger *trigger4 = [UNLocationNotificationTrigger triggerWithRegion:region repeats:NO];
複製程式碼

發出通知

NSString *requestIdentifier = @"sampleRequest";

 UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier
 content:content  trigger:trigger1];
 UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {

    }];
複製程式碼

3.接收本地通知並處理。 與LocalNotificationL類似,有三種情況

(1).前臺接收

(2).後臺未殺死程式進入前臺接收

(3).程式已經殺死,點選通知訊息啟動app 需要遵循UNUserNotificationCenterDelegate代理協議方法

center.delegate = self;
複製程式碼

通過以下兩個UNUserNotificationCenterDelegate的方法實現

 // The method will be called on the delegate only if the application is in the foreground. If the method is not implemented or the handler is not called in a timely manner then the notification will not be presented. The application can choose to have the notification presented as a sound, badge, alert and/or in the notification list. This decision should be based on whether the information in the notification is otherwise visible to the user.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);

// The method will be called on the delegate when the user responded to the notification by opening the application, dismissing the notification or choosing a UNNotificationAction. The delegate must be set before the application returns from application:didFinishLaunchingWithOptions:.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler __IOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0) __TVOS_PROHIBITED;
複製程式碼

實現如下:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{
    NSLog(@"willPresentNotification:%@",notification.request.content.title);
    
    // 這裡真實需要處理互動的地方
    // 獲取通知所帶的資料
    NSString *apsContent = [notification.request.content.userInfo objectForKey:@"type"];
    NSLog(@"%@",apsContent);
    
    
}
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
    //在沒有啟動本App(包括後臺執行中)時,收到伺服器推送訊息,下拉訊息會有快捷回覆的按鈕,點選按鈕後呼叫的方法,根據identifier來判斷點選的哪個按鈕
    NSString *apsContent = [response.notification.request.content.userInfo objectForKey:@"type"];
    NSLog(@"didReceiveNotificationResponse:%@",response.notification.request.content.title);
    NSLog(@"%@",apsContent);

}
複製程式碼

我們可已通過removeIdentifier刪除計劃的推送事件:

[center removePendingNotificationRequestsWithIdentifiers:@[requestIdentifier]];
複製程式碼

如果我們需要更新推送,可以通過 addNotificationRequest: 方法,在 Identifier 不變的情況下重新新增,就可以重新整理原有的推送。

相關文章