先回憶一下,推送通知有5種不一樣的呈現效果(另外還會在 「通知中心」 進行展現,就是頂端下拉屏幕後的視圖):ios
一、在屏幕頂部顯示一塊橫幅(顯示具體內容)小程序
二、在屏幕中間彈出一個UIAlertView(顯示具體內容) 不多不多使用這種,,用戶體驗不好數組
三、在鎖屏界面顯示一塊橫幅(鎖屏狀態下,顯示具體內容)服務器
四、更新app圖標的數字(說明新內容的數量)網絡
五、播放音效(提醒做用)app
咱們開始正式配置本地和遠程兩種推送,而且着重從本地推送開始,由於遠程推送的代碼實現,須要本地推送的基礎~~~~ide
1、如何發出本地推送通知:三步走 + 註冊通知(iOS8.0以後才須要,因此當心坑,要作iOS7的適配)fetch
一、建立本地推送通知對象ui
UILocalNotification *ln = [[UILocalNotification alloc] init];atom
二、設置本地推送通知屬性
(1)推送通知的觸發時間(什麼時候發出推送通知)
@property(nonatomic,copy) NSDate *fireDate;
(2)推送通知的具體內容
@property(nonatomic,copy) NSString *alertBody;
(3)在鎖屏時顯示的動做標題(完整標題:「滑動來」 + alertAction)
@property(nonatomic,copy) NSString *alertAction;
(4)音效文件名
@property(nonatomic,copy) NSString *soundName;
(5)app圖標數字
@property(nonatomic) NSInteger applicationIconBadgeNumber;
(6)每隔多久重複發一次推送通知
@property(nonatomic) NSCalendarUnit repeatInterval;
(7)點擊推送通知打開app時顯示的啓動圖片,不設置則沒有,若是設置(不管設置成什麼),只會顯示app啓動的圖片,很坑的一個屬性
@property(nonatomic,copy) NSString *alertLaunchImage;
(8)附加的額外信息
@property(nonatomic,copy) NSDictionary *userInfo;
(9)時區
@property(nonatomic,copy) NSTimeZone *timeZone;
(通常設置爲[NSTimeZone defaultTimeZone] ,跟隨手機的時區)
(10)在通知中內心顯示的標題
@property(nonatomic,copy) NSString *title;
(11)顯示滑動解鎖的按鈕:設置成no,則顯示「滑動來查看」,不顯示用戶設定的內容
@property(nonatomic) BOOL *hasAction;
三、推送通知的發出
(1)調度本地推送通知(調度完畢後,推送通知會在特意時間fireDate發出)
[[UIApplication sharedApplication] scheduleLocalNotification:ln];
(2)得到被調度(定製)的全部本地推送通知
@property(nonatomic,copy) NSArray *scheduledLocalNotifications;
(已經發出且過時的推送通知就算調度結束,會自動從這個數組中移除)
(3)取消調度本地推送通知
- (void)cancelLocalNotification:(UILocalNotification *)notification;
- (void)cancelAllLocalNotifications;
(4)當即發出本地推送通知
- (void)presentLocalNotificationNow:(UILocalNotification *)notification;
2、點擊本地推送通知的響應
正常狀況點擊彈出的通知,會打開應用程序,因此,這裏的響應,指的是「即將進入前臺」
一、當用戶點擊本地推送通知,會自動打開app,這裏有3種狀況
(1) 狀態:app並無關閉,一直隱藏在後臺;
操做:讓app進入前臺,並會調用AppDelegate的下面方法(並不是從新啓動app,而是即將進入前臺的響應)
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
(2) 狀態:app在前臺運行;
操做:推送通知仍然會在發送,也會走下面的方法,雖然沒有跳轉到app
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
(3) 狀態:app已經被關閉(進程已死)
操做:啓動app,啓動完畢會調用AppDelegate的下面方法,不會調用上面的方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
launchOptions參數經過UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知對象
二、關於頁面跳轉的邏輯判斷(要進行程序所處狀態的邏輯判斷,,哎呀,若是屢不清看下面代碼。。)
(1)程序在前臺運行時,不須要根據本地推送進行跳轉操做
(2)程序在後臺運行時,跳轉到通知邏輯指定的頁面
(3)程序關閉時,跳轉到通知邏輯指定的頁面
(4)程序第一次運行(本地推送尚未發生),是不須要加載推送通知邏輯的
三、要結合app的生命週期方法和狀態值,來進行上面業務邏輯的判斷
(1)Not running 未運⾏,程序沒啓動。
(2)Inactive 未激活,程序在前臺運⾏,不過沒有接收到事件。在沒有事件處理狀況下程序一般停留在這個狀態。
(3)Active 激活,程序在前臺運行並且接收到了事件。這也是前臺的一個正常的模式。
(4)Backgroud 後臺,程序在後臺並且能執⾏代碼,大多數程序進⼊這個狀態後會在這個狀態上停留⼀ 會兒。
(5)Suspended 上一狀態時間到了以後會進入掛起狀態。有的程序通過特殊的請求後能夠長期處於Backgroud狀態,Suspended 掛起程序在後臺不能執⾏代碼。系統會自動把程序變成這個狀態並且不會發出通知。當掛起時,程序仍是停留在內存中的,當系統內存低時,系統就把掛起的程序清除掉,爲前臺程序提供更多的內存。
四、給出一個參考示例:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 設置應用程序的圖標右上角的數字 [application setApplicationIconBadgeNumber:0];
//適配 iOS7.0,大於7.0的版本再去註冊通知 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; } // 界面的跳轉(針對應用程序被殺死的狀態下的跳轉,這裏判斷鍵值是否存在,若是存在,說明是接受到通知以後開啓的app,那麼就執行跳轉) if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) { // 跳轉代碼(只是簡單的示範,redview中會打印出字典的內容,用來查看接受到通知攜帶的內容) UILabel *redView = [[UILabel alloc] init]; redView.frame = CGRectMake(0, 0, 200, 300); redView.numberOfLines = 0; redView.font = [UIFont systemFontOfSize:12.0]; redView.backgroundColor = [UIColor redColor]; redView.text = [NSString stringWithFormat:@"%@", launchOptions]; [self.window.rootViewController.view addSubview:redView]; } return YES; } /* 點擊通知,應用程序正在進入前臺;或者在前臺的時候都會執行該方法 */ - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { // 針對應用程序在後臺的時候進行的跳轉,若是程序在前臺不用跳轉
//注意此時的應用程序狀態! if (application.applicationState == UIApplicationStateInactive) { NSLog(@"進行界面的跳轉"); NSLog(@"%@", notification.userInfo); UIView *redView = [[UIView alloc] init]; redView.frame = CGRectMake(0, 0, 100, 100); redView.backgroundColor = [UIColor redColor]; [self.window.rootViewController.view addSubview:redView]; } }
3、關於註冊通知(得到許可)的補充介紹
一、從iOS 8.0開始,若是要使用通知,須要獲得用戶的許可,也就是彈出一個提示框,詢問用戶是否受權。這個選擇也能夠在手機的「設置」中進行配置(包括推送通知顯示的位置也能夠選擇)。
二、設置方式
(1)設置setting,作一些配置,包括推送通知能夠顯示的類型
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];
(2)應用程序對象註冊推送
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
(3)關於分類categories
經過分類能夠給推送通知添加快捷回覆,包括按鈕和文本框,好比QQ的快捷回覆,微博的快捷點贊等功能。
4、單獨說一下 category的設置
一、在通知處顯示按鈕,能夠點擊進行快捷回覆,默認會回到程序中。另外能夠設置快捷回覆的文本框,進行信息發送。這些按鈕是能夠設置響應事件,進行邏輯實現的!
二、設置
(1)配置可變的category對象
UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc]init];
(2)設置標識符,這個必須有,通知對象根據這個標識,從註冊的category中找到指定的,設置本身的category屬性
category.identifier = @"cate";
(3)爲category 準備 action(動做按鈕),這點相似 alertViewController
UIMutableUserNotificationAction*action = [[UIMutableUserNotificationAction alloc]init]; action.title = @「已閱讀」; action.identifier = @"action1」; //讓按鈕的響應在後臺處理,不用跳轉到應用程序中去 action.activationMode = UIUserNotificationActivationModeBackground; //true時,用戶在點擊動做以前必須確認本身的身份 action.authenticationRequired = NO; //在通知中心顯示不一樣背景顏色 action.destructive = NO;
(4)設置快捷回覆的文本框,點擊按鈕出現輸入文本框進行快捷回覆
action.behavior = UIUserNotificationActionBehaviorTextInput;
(5)添加動做到分類
[category setActions:@[action1,action2] forContext:UIUserNotificationActionContextDefault];
(6)在註冊通知的時候,添加分類進去
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:[NSSet setWithObjects:category, nil]];
[[UIApplication sharedApplication]registerUserNotificationSettings:setting];
三、動做按鈕的響應(application的代理方法),在這裏面進行業務邏輯的實現
(1)動做按鈕的響應事件————不帶文本框信息
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler if ([identifier isEqualToString:@"action1」]) { //點擊了標記已讀 NSLog(@"點擊了標記已讀"); } if ([identifier isEqualToString:@"action2」]) { //點擊了刪除 NSLog(@"點擊了刪除"); } //這裏執行一下block completionHandler(); }
(2)動做按鈕的響應事件————快捷回覆帶文本框信息(和上面的方法不要一塊兒寫)
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler { if ([identifier isEqualToString:@"action2」]) { //點擊了標記已讀 //注意key NSLog(@"%@",responseInfo[UIUserNotificationActionResponseTypedTextKey]); } completionHandler(); }
5、遠程推送的原理
一、蘋果的服務器會和全部的iPhone創建長鏈接(不懂長鏈接去找度娘),因此,蘋果能夠經過這個長鏈接,實現對全部用iPhone手機的時間校準、系統升級、查找位置等等操做(廢話,由於一直和手機連着網麼。。。),於是,服務器也能夠實現給全部用戶發送通知消息,而後用戶手機接收到後,針對不一樣的應用,實現相似本地推送的展現效果。 然而蘋果的服務器怎麼知道發送什麼東西呢----->咱們的app後臺服務器告訴他的;可是咱們的後臺服務器以及蘋果的服務器又是怎麼肯定發送給哪一個手機和應用的呢----->經過標識 deviceToken。。。最後蘋果的這個「服務器」,準確的說是服務,叫作 : APNs (Apple Push Notification Service)。
二、遠程推送流程詳解
deviceToken:就是由UDID 和 bundleID 生成的惟一標識符
(1) 設備(應用)向蘋果服務器請求得到deviceToken
(2)蘋果根據請求信息,生成deviceToken,並將其返回給設備
(3)設備把收到的deviceToken發送給應用的後臺服務器,這時服務器記錄下了deviceToken
(4)應用的服務器須要發送推送時,附加這deviceToken發送給APNs(蘋果服務器)
(5)蘋果接受到推送後,根據deviceToken,把信息傳達給和他保持長鏈接的iPhone設備
(6)設備監聽並接受到遠程推送,執行相似本地推送的展現
6、遠程推送實現的準備工做
一、開發iOS程序的推送功能, iOS端須要作的事
(1) 應用向蘋果服務器請求得到deviceToken
(2)獲得蘋果返回的deviceToken
(3)發送deviceToken給應用的後臺服務器,這時(本身的)服務器記錄下了deviceToken
(4)監聽用戶對通知的點擊
二、調試iOS的遠程推送功能, 必備條件:
(1)真機,模擬器玩不了咯
(2)調試推送須要的證書文件:悲劇的你,須要申請開發者帳號了,,不貴,我的帳號也就688元
1> development.cer : 調試推送證書 。 某臺電腦就能調試某個app的推送服務
2> mobileprovision : 描述文件。 某臺電腦就能利用某臺設備調試某個程序(關聯上了設備)
補充一下:證書的類型(沒有開發經驗的弟弟們常常搞不清楚的東西),描述文件是根據證書和註冊設備生成的
(3)發佈具備推送服務的app
1> production.cer : 若是發佈的程序中包含了推送服務,就必須安裝這個證書
2> mobileprovision : 某臺電腦就能發佈某個程序
三、遠程推送準備的流程概述
(1)登陸開發者帳號, 建立App ID:說明哪一個App使用推送,綁定bundleID,注意AppID是全稱,不能帶*(通配的模式不行)
(2) 爲App ID建立APNs SSL證書:就是上面說的推送證書,這裏要關聯上面的AppID
(3) 生成描述文件:根據上面兩個東西生成的--> 最終肯定 「哪臺設備要在哪臺電腦上調試哪一個程序」
(4)把證書和描述文件下載安裝了:雙擊,最好先裝cer
7、開始代碼配置~~
上面的工做是遠程推送的準備工做,設置完畢後,咱們就能夠進行代碼實現了,不少代碼邏輯和本地推送相似
一、註冊通知,請求deviceToken(只要註冊了,就自動發出請求,可是要注意ios版本問題!)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { //iOS8 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:settings]; [application registerForRemoteNotifications]; } else { // 適配iOS7 [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeNewsstandContentAvailability | UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert]; }
//這裏相似本地推送的邏輯實現,要判斷是否須要跳轉 if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) { // 跳轉 // 添加一個紅色的View } return YES; }
二、得到deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // 業務邏輯:將DeviceToken傳給服務器 NSLog(@"%@", deviceToken.description); }
三、假設服務器開始發送推送了,接收到推送
(1)服務器發過來的信息有固定格式(userInfo),類比本地推送對象的屬性:經過這些格式能夠肯定--> 聲音、badge、額外的字段、推送信息等內容
(2)可使用pushMeBaby這個小程序模擬服務器發送推送~~
(3)這個方法就是相似本地推送時得到推送的響應方法,注意判斷是否跳轉。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { NSLog(@"%@", userInfo); }
四、還有一種接受推送的方式:後臺處理
(1)應用程序接收到推送以後,就當即響應,用戶不用操做(不用點擊通知),在「靜默」的狀況下,實現了推送想實現的邏輯
(2)推送信息(userInfo)中必須包含字段:"content-available":"1",其中 「1」隨便寫
(3)實現下面的代碼,注意裏面有回調block,須要告訴系統是否有新內容(枚舉常量)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSLog(@"雖然用戶沒有察覺,可是已經接受到通知"); UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; redView.frame = CGRectMake(100, 100, 100, 100); [self.window.rootViewController.view addSubview:redView]; // 1.打開後臺模式 2.告訴系統是否有新內容的更新 3.發送的通知有固定的格式("content-available":"1") completionHandler(UIBackgroundFetchResultNewData); }
(3)還要有額外的配置,來實現後臺運行
8、總結
好了,推送的東西講完了,關於如何申請開發者帳號、申請調試證書、註冊設備、生成描述文件之類的事情,你們就靠度娘吧,其實也很簡單,記住上文中的證書類型頁面就好,就那麼幾種。
另外,蘋果的服務器有時候會抽風。。。deviceToken不能及時獲取,你們多試幾遍,或者找較好的網絡環境試試。。
後面有機會給你們介紹第三方的推送,,那個纔是真正的應用(貌似白寫了這麼多。。。)