學(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
{
}