iOS推送通知

學(xué)習(xí)iOS開發(fā)已經(jīng)兩年多了,推送方面一直使用第三方極光推送,對(duì)推送沒(méi)有進(jìn)行系統(tǒng)的學(xué)習(xí)。今天我就把推送相關(guān)的知識(shí)點(diǎn)梳理一遍,以供以后的復(fù)習(xí)與查閱。

iOS 的推送分為本地推送和遠(yuǎn)程推送。

本地推送

待完善。。。 (偷個(gè)懶??)

遠(yuǎn)程推送

1.要先去開發(fā)者官網(wǎng)配置推送證書和描述文件
2.在Xcode里點(diǎn)擊項(xiàng)目 -> Capabilities 里打開推送功能 (不然獲取不到deviceToken)
3.注冊(cè)通知

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {

    //注冊(cè)通知 (iOS8 和 iOS 10 推送發(fā)生了改變)


    if(@available(iOS10.0, *))
    {
        //iOS10 及以后注冊(cè)通知

        //請(qǐng)求通知權(quán)限, 本地和遠(yuǎn)程共用
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        [center requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError * _Nullable error) {

            if(granted)
            {
                NSLog(@"請(qǐng)求成功");
            }
            else
            {
                NSLog(@"請(qǐng)求失敗");
            }

        }];

        //注冊(cè)遠(yuǎn)程通知
        [application registerForRemoteNotifications];

        //設(shè)置通知的代理
        center.delegate=self;
    }
    else if ( [UIDevice currentDevice].systemVersion.floatValue >= 8.0 )
    {
        //iOS8 及以后注冊(cè)通知

        //1. 配置通知類型
        /*
         UIUserNotificationTypeBadge  = 1 << 0,  //角標(biāo)
         UIUserNotificationTypeSound  = 1 << 1,  //聲音
         UIUserNotificationTypeAlert  = 1 << 2,  //提醒
         */
        UIUserNotificationType type = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;

        //2. 配置settings
        UIUserNotificationSettings * settings = [UIUserNotificationSettings settingsForTypes:type categories:nil];

        //3. 注冊(cè)settings
        [application registerUserNotificationSettings:settings];

        //4. 注冊(cè)遠(yuǎn)程通知
        [application registerForRemoteNotifications];
    }
    else
    {
        //iOS8 以下注冊(cè)通知

        //1. 配置通知的類型
        /*
         UIRemoteNotificationTypeBadge  = 1 << 0,  //角標(biāo)
         UIRemoteNotificationTypeSound  = 1 << 1,  //聲音
         UIRemoteNotificationTypeAlert  = 1 << 2,  //提醒
         */
        UIRemoteNotificationType type = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert;

        //2. 注冊(cè)遠(yuǎn)程通知
        [application registerForRemoteNotificationTypes:type];
    }


    return YES;
}

4.獲取deviceToken
//當(dāng)完成注冊(cè)遠(yuǎn)程通知時(shí),接收蘋果服務(wù)器返回的deviceToken
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"deviceToken = %@", deviceToken);
    
    //發(fā)送deviceToken給公司服務(wù)器 (一般情況下,手機(jī)不做刪除操作,deviceToken每次運(yùn)行是不變的)
}
5.收到通知的代理
//當(dāng)接收到遠(yuǎn)程推送值的時(shí)候會(huì)調(diào)用 (此方法只有在前臺(tái)和后臺(tái)時(shí)才會(huì)調(diào)用。app沒(méi)啟動(dòng)時(shí),點(diǎn)擊推送進(jìn)來(lái)不會(huì)調(diào)用,需要在didFinishLaunchingWithOptions:里額外處理)
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    
    /*
    UIApplicationStateActive,      //激活 (前臺(tái))
    UIApplicationStateInactive,    //將要激活 (將要進(jìn)入前臺(tái))
    UIApplicationStateBackground   //后臺(tái)
    */
    if ( [UIApplication sharedApplication].applicationState == UIApplicationStateActive )
    {
        //如果程序在前臺(tái)運(yùn)行,那么我們不應(yīng)該主動(dòng)發(fā)生跳轉(zhuǎn)行為 (也可以給用戶提示一下,比如QQ是聲音,微信是震動(dòng))
        NSLog(@"前臺(tái)收到通知:%@", userInfo);
        return;
    }
    else
    {
        NSLog(@"后臺(tái)收到通知:%@", userInfo);
    }
    
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    view.backgroundColor = [UIColor redColor];
    [self.window.rootViewController.view addSubview:view];
}

//程序沒(méi)啟動(dòng)時(shí)收到通知的額外處理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    //收到通知的處理 (iOS7及以下的額外處理)(點(diǎn)擊收到的通知進(jìn)入app后,如果是首次啟動(dòng),不會(huì)執(zhí)行收到通知的代理,需要在這個(gè)方法進(jìn)行處理)
    if ( launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] )
    {
        NSDictionary * dict = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
        UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
        label.numberOfLines = 0;
        label.backgroundColor = [UIColor yellowColor];
        label.text = [NSString stringWithFormat:@"launchOptions = %@", dict];
        [self.window.rootViewController.view addSubview:label];
    }

    return YES;
}

//寫了這個(gè)方法,上個(gè)方法就不會(huì)再調(diào)用了
//如果實(shí)現(xiàn)了這個(gè)方法,還要打開一個(gè)選項(xiàng)值 -> 點(diǎn)擊項(xiàng)目 -> Capabilities -> UIBackgroundModes -> 勾選Remote notifications (如果沒(méi)打開會(huì)打印出警告信息)
//當(dāng)接收到遠(yuǎn)程推送值的時(shí)候會(huì)調(diào)用 (此方法在臺(tái)、后臺(tái)、退出時(shí)都會(huì)調(diào)用 iOS7新增的方法)
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    /*
     UIApplicationStateActive,      //激活 (前臺(tái))
     UIApplicationStateInactive,    //將要激活 (將要進(jìn)入前臺(tái))
     UIApplicationStateBackground   //后臺(tái)
     */
    if ( [UIApplication sharedApplication].applicationState == UIApplicationStateActive )
    {
        //如果程序在前臺(tái)運(yùn)行,那么我們不應(yīng)該主動(dòng)發(fā)生跳轉(zhuǎn)行為 (也可以給用戶提示一下,比如QQ是聲音,微信是震動(dòng))
        NSLog(@"前臺(tái)收到通知:%@", userInfo);
        return;
    }
    else
    {
        NSLog(@"后臺(tái)收到通知:%@", userInfo);
    }
    
    UIView * view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    view.backgroundColor = [UIColor redColor];
    [self.window.rootViewController.view addSubview:view];
    
    
    //當(dāng)實(shí)現(xiàn)此方法時(shí),系統(tǒng)就會(huì)讓我們調(diào)用此方法
    //需要傳人一個(gè)值,這個(gè)值告訴蘋果,當(dāng)通知發(fā)過(guò)后,自己有沒(méi)有處理成功 (默認(rèn)傳入U(xiǎn)IBackgroundFetchResultNewData即可)
    /*
     UIBackgroundFetchResultNewData,  //新數(shù)據(jù)
     UIBackgroundFetchResultNoData,   //沒(méi)有數(shù)據(jù)
     UIBackgroundFetchResultFailed    //請(qǐng)求失敗
     */
    completionHandler(UIBackgroundFetchResultNewData);
}
#pragma mark - UNUserNotificationCenterDelegate ( iOS10 之后)

/*
 iOS10之后前臺(tái)運(yùn)行收到通知 會(huì)調(diào)用的方法
 (iOS10之前, 在前臺(tái)運(yùn)行時(shí), 不會(huì)出現(xiàn)通知的橫幅)
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
API_AVAILABLE(ios(10.0)){
    NSDictionary *userInfo = notification.request.content.userInfo;
    
    NSLog(@"iOS10及以后 前臺(tái)收到推送: %@", userInfo);
    
    //在前臺(tái)運(yùn)行收到通知后, 有哪些效果呈現(xiàn)(聲音/提醒/數(shù)字角標(biāo))
    completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
}


/*
 iOS10之后 后臺(tái)運(yùn)行及程序退出收到通知 會(huì)調(diào)用的方法
 */
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler
API_AVAILABLE(ios(10.0)){
    
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    
    NSLog(@"iOS10及以后 后臺(tái)收到推送: %@", userInfo);
    
    completionHandler();
}



總結(jié)

如果在前臺(tái)收到通知時(shí),不需要出現(xiàn)通知的橫幅和聲音,其實(shí)寫下面這一個(gè)代理其實(shí)就可以了,這個(gè)方法在臺(tái)、后臺(tái)、退出都能收到通知。

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
}

iOS10之后新出的兩個(gè)代理,調(diào)用了下面的方法后,上面的方法就不會(huì)再調(diào)用了。(如果沒(méi)寫下面兩個(gè)方法,iOS10之后的系統(tǒng)也會(huì)調(diào)用上面的方法。)

// iOS10之后前臺(tái)運(yùn)行收到通知 會(huì)調(diào)用的方法 
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
{
}
 //iOS10之后 后臺(tái)運(yùn)行及程序退出收到通知 會(huì)調(diào)用的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler
{
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。