本地通知:就是指不需要互聯(lián)網(wǎng)就能發(fā)出的推送通知(不需要服務(wù)器去支持),使用的場景一般是定時提醒用戶完成一些任務(wù),例如清理垃圾,看定影,記賬等。在IOS8之后本地通知還需要注冊用戶權(quán)限。
通知行為:前臺通知行為,后臺通知行為
設(shè)置本地通知屬性(推薦一個一個屬性測試運(yùn)行)
// 1.設(shè)置通知的內(nèi)容(如果此屬性不設(shè)置是不會發(fā)送通知的)
ln.alertBody = @"小明,你媽叫你回家吃飯了!";
//? 2.設(shè)置通知觸發(fā)的開始時間
ln.fireDate = [NSDate dateWithTimeIntervalSinceNow:3];
//? 3.設(shè)置重復(fù)通知的時間,間隔
ln.repeatInterval = NSCalendarUnitSecond;
//? 4.設(shè)置重復(fù)執(zhí)行使用日歷(用戶設(shè)置的日歷)
ln.repeatCalendar = [NSCalendar? currentCalendar];
//? ? NSString * const NSGregorianCalendar; 公歷
//? ? NSString * const NSChineseCalendar; 農(nóng)歷
//? ? ln.repeatCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSChineseCalendar];
//? 5.設(shè)置應(yīng)用圖標(biāo)右上角的數(shù)字
ln.applicationIconBadgeNumber = 3;
//? 6.設(shè)置點(diǎn)擊推送通知進(jìn)入界面的時候顯示,加載圖片
ln.alertLaunchImage = @"";
//? 7 設(shè)置通知的音效(只有真機(jī)有效)
local.soundName = UILocalNotificationDefaultSoundName;
//? 8 設(shè)置一些額外信息
local.userInfo = @{@"QQ":@"55555",@"info":@"約了沒"};
//? iOS8.0 以后新增屬性
//? ************************************
//? 1.設(shè)置區(qū)域,進(jìn)入或離開某個區(qū)域的時候觸發(fā)
//? ? CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(40.1,106.1);
//? ? ln.region = [[CLCircularRegion alloc] initWithCenter:coordinate radius:10.0 identifier:@"ab"];
//? 2.設(shè)置進(jìn)入或離開某個區(qū)域只執(zhí)行一次
//? ? ln.regionTriggersOnce = YES;
//? ***************************************
//? iOS8.2 新增屬性
//? ? ln.alertTitle = @"通知標(biāo)題";
AppDelegate本地通知代理方法:
*? 一旦接收到本地通知就會調(diào)用該方法
*? 注意這個方法:應(yīng)用在前臺也會調(diào)用
*? @param application? 應(yīng)用
*? @param notification 本地通知對象
- (void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
//? 當(dāng)應(yīng)用在前臺時候什么都不做
if (application.applicationState == UIApplicationStateActive) {
return;
}
//? 當(dāng)應(yīng)用不再前臺的時候才去跳轉(zhuǎn),這樣用戶體檢更好
UITabBarController *tbVc = (UITabBarController *)application.keyWindow.rootViewController;
tbVc.selectedIndex = 1;
}
但是當(dāng)應(yīng)用被干掉的時候,不在調(diào)用application:didReceiveLocalNotification:的代理方法,但我們知道當(dāng)應(yīng)用程序啟動的時候一定會調(diào)用application: didFinishLaunchingWithOptions:的代理方法,在這里我們能拿到本地通知信息,也可以跳轉(zhuǎn)相應(yīng)的界面
//? 如果是點(diǎn)擊本地通知進(jìn)來的那么launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]就會有內(nèi)容
if(launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]){
//頁面跳轉(zhuǎn)
UITabBarController *tbVc = (UITabBarController *)self.window.rootViewController;
tbVc.selectedIndex = 1;
}
點(diǎn)擊不同的通知跳轉(zhuǎn)不同的界面的方法:
在發(fā)送通知時候,設(shè)置userInfo屬性
// ?設(shè)置應(yīng)用信息
ln.userInfo = @{@"pageKey":@"friend"};
在AppDelegate本地通知代理方法中進(jìn)行判斷
/**
*? 一旦接收到本地通知就會調(diào)用該方法
*? 注意這個方法:應(yīng)用在前臺也會調(diào)用
*? @param application? 應(yīng)用
*? @param notification 本地通知對象
*/
- (void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
//? 當(dāng)應(yīng)用在前臺時候什么都不做
if (application.applicationState == UIApplicationStateActive) {
return;
}
//? 當(dāng)應(yīng)用不再前臺的時候才去跳轉(zhuǎn),這樣用戶體檢更好
//? 獲取tabBarController
UITabBarController *tbVc = (UITabBarController *)self.window.rootViewController;
//? 獲取用戶設(shè)置的跳轉(zhuǎn)頁
NSString *page = notification.userInfo[@"pageKey"];
//? 如果是朋友圈
if ([page isEqualToString:@"session"]) {
tbVc.selectedIndex = 1;
}else{
//? ? ? 否則跳轉(zhuǎn)到好友
tbVc.selectedIndex = 0;
}
}
我們?nèi)〕鯱ILocalNotification對象,剩下的做法與接收到本地通知代理方法中處理相同,所以我們把它提取為一個公用的方法
/**
*? 根據(jù)通知跳轉(zhuǎn)到不同頁面
*/
- (void) jumpToPageWithLocalNotification:(UILocalNotification *) notification
{
//? 獲取tabBarController
UITabBarController *tbVc = (UITabBarController *)self.window.rootViewController;
//? 獲取用戶設(shè)置的跳轉(zhuǎn)頁
NSString *page = notification.userInfo[@"pageKey"];
//? 如果是朋友圈
if ([page isEqualToString:@"session"]) {
tbVc.selectedIndex = 0;
}else{
//? ? ? 否則跳轉(zhuǎn)到好友
tbVc.selectedIndex = 1;
}
}
在didReceiveLocalNotification方法中
/**
*? 一旦接收到本地通知就會調(diào)用該方法
*? 注意這個方法:應(yīng)用在前臺也會調(diào)用
*? @param application? 應(yīng)用
*? @param notification 本地通知對象
*/
- (void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
//? 當(dāng)應(yīng)用在前臺時候什么都不做
if (application.applicationState == UIApplicationStateActive) {
return;
}
//? 當(dāng)應(yīng)用不再前臺的時候才去跳轉(zhuǎn),這樣用戶體檢更好
[self jumpToPageWithLocalNotification:notification];
}
在didFinishLaunchingWithOptions方法中
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//? 如果是點(diǎn)擊本地通知進(jìn)來的那么launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]就會有內(nèi)容
UILocalNotification *notifcation = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
//? 如果存在通知
if(notifcation){
[self jumpToPageWithLocalNotification:notifcation];
}
return YES;
}
用戶點(diǎn)擊本地推送通知,會自動打開APP,分為兩種情況:
app并沒有關(guān)閉,一直隱藏在后臺,讓app進(jìn)入前臺,并會調(diào)用AppDelegate的下面方法(并非重新啟動app)
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
app已經(jīng)被關(guān)閉(進(jìn)程已死)啟動app,啟動完畢會調(diào)用AppDelegate的下面方法
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
aunchOptions參數(shù)通過UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知對象
基于位置的通知:當(dāng)用戶進(jìn)入或者離開某個位置就會發(fā)送通知(IOS8之后才有的),需要設(shè)置requestWhenInUseAuthorization
遠(yuǎn)程通知:顧名思義,就是從遠(yuǎn)程服務(wù)器推送給客戶端的通知(需要聯(lián)網(wǎng)),遠(yuǎn)程推送服務(wù),又稱為APNs(ApplePush Notification Services),為什么要使用遠(yuǎn)程通知?因?yàn)橛脩絷P(guān)閉了APP就無法收到服務(wù)器最新的數(shù)據(jù),但是遠(yuǎn)程通知服務(wù)可以無視用戶APP是否開啟,只要聯(lián)網(wǎng)了,就能收到服務(wù)器遠(yuǎn)程推送的通知。
遠(yuǎn)程通知的示意圖:

?所有的蘋果設(shè)備,在聯(lián)網(wǎng)狀態(tài)下,都會與蘋果的服務(wù)器建立長連接
什么是長連接:只要聯(lián)網(wǎng)了,就一直建立連接
長連接的作用 1.時間校準(zhǔn) 2.系統(tǒng)升級 3.查找我的iPhone
長連接的好處 1.數(shù)據(jù)傳輸速度快 2.數(shù)據(jù)保持最新狀態(tài)

實(shí)現(xiàn)遠(yuǎn)程推送通知的過程
1 真機(jī) ?
2 證書
開發(fā)階段
aps_development.cer 讓某個電腦具備調(diào)試遠(yuǎn)程推送通知的能力
ios_development.cer 讓某個電腦具有真機(jī)調(diào)試的能力
dev_qq.mobileprovision 讓某個電腦上可以在某個真機(jī)上調(diào)試某個App的遠(yuǎn)程推送服務(wù)
發(fā)布階段
aps_production.cer 讓電腦具備發(fā)布某個具有遠(yuǎn)程推送服務(wù)的App的能力
ios_distribution.cer 讓電腦具備發(fā)布程序的能力
dis_qq.mobileprovision 讓某臺電腦具備發(fā)布某App的能力
從APNs服務(wù)器上獲取deviceToken

配置遠(yuǎn)程推送通知證書?
遠(yuǎn)程推送代碼實(shí)現(xiàn)
在iOS7下
注冊遠(yuǎn)程通知
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//? ? UIRemoteNotificationTypeBadge? = 1 << 0, 應(yīng)用圖標(biāo)右上角數(shù)字
//? ? UIRemoteNotificationTypeSound? = 1 << 1, 聲音
//? ? UIRemoteNotificationTypeAlert? = 1 << 2, 提示
//? ? UIRemoteNotificationTypeNewsstandContentAvailability = 1 << 3, 新聞,國內(nèi)幾乎沒人使用
//? 遠(yuǎn)程通知類型
UIRemoteNotificationType remoteTypes = UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert;
// 注冊遠(yuǎn)程通知(在iOS8被廢棄了)
[application registerForRemoteNotificationTypes:remoteTypes];
return YES;
}
實(shí)現(xiàn)注冊遠(yuǎn)程通知返回deviceToken的回調(diào)方法
/**
*? 當(dāng)APNs返回deviceToken會調(diào)用,該方法
*
*? @param application 當(dāng)前應(yīng)用對象
*? @param deviceToken 設(shè)備令牌
*/
- (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSLog(@"%@",deviceToken);
}
實(shí)現(xiàn)注冊遠(yuǎn)程通知失敗回調(diào)方法,用于檢查失敗原因方便調(diào)試
/**
*? 當(dāng)從APNs獲取deviceToken失敗的時候會回調(diào)該方法
*
*? @param application 應(yīng)用
*? @param error? ? ? 錯誤
*/
- (void) application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(@"%@",error);
}
實(shí)現(xiàn)點(diǎn)擊遠(yuǎn)程通知,進(jìn)入App調(diào)用的方法
/**
*? 處理點(diǎn)擊遠(yuǎn)程通知的頁面跳轉(zhuǎn)處理
*/
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(@"%s",__FUNCTION__);
}