推送-遠(yuǎn)程通知推送教程

前言

本文是一篇轉(zhuǎn)載文章,在這一篇實用的文章里,你可以按照上面的步驟實現(xiàn)不借助第三方和服務(wù)器端,自己給自己的設(shè)備發(fā)推送通知。真的好棒,從中你可以領(lǐng)悟一些推送的核心用法。


本文翻譯自:raywenderlich.com,原文作者:Jack Wu,譯者:JMStack

iOS開發(fā)者們喜歡想象他的用戶們會每時每刻使用他們所開發(fā)的APP,但是殘酷的事實是他們的用戶會有關(guān)閉APP來處理其它事情的時候。就像你洗好的衣服總要人去疊吧。
幸好,推送通知功能可以讓開發(fā)者與用戶建立連接并進(jìn)行簡單的交互,即使用戶當(dāng)前并沒有使用APP!
從推送通知功能第一次問世到現(xiàn)在已經(jīng)變得越來越強(qiáng)大。在iOS 9上,遠(yuǎn)程推送可以做到:

  • 顯示短文本

  • 播放通知提示音

  • 設(shè)置APP圖標(biāo)的角標(biāo)

  • 在不打開APP的情況下,允許用戶與APP交互

  • 允許APP在后臺靜默喚醒來執(zhí)行任務(wù)

這份遠(yuǎn)程推送通知教程會告訴你遠(yuǎn)程推送的工作原理的并讓你了解它的一些特性。
在開始推送測試之前你需要具備以下條件:

  • 一臺iOS設(shè)備。遠(yuǎn)程推送不能在摸擬器上運(yùn)行,所以你需要一臺真機(jī)。

  • 一個開發(fā)者帳號。從Xcode7開始,在真機(jī)上測試APP不再需要加入開發(fā)者計劃。但是為了配置遠(yuǎn)程推送,你需要有一個與APP ID對應(yīng)的推送證書,獲得這個證書你需要加開發(fā)者計劃。

開始

為了接收發(fā)送遠(yuǎn)程推送通知你必須完成以下3個主要的任務(wù):

1、App必須正確配置并注冊APNS(Apple Push Notification Service),以便所有設(shè)置都完成時就能馬上接收到通知。

2、服務(wù)端必須向APNS發(fā)送一條明確指向一個或多個設(shè)備的通知。

3、App必需接收服務(wù)端發(fā)送的通知,App可以執(zhí)行通知包含的任務(wù)或者在application的代理(delegate)回調(diào)方法內(nèi)處理用戶交互行為。

任務(wù)1和任務(wù)3是這份推送通知教程主要關(guān)注的內(nèi)容,因為這兩個任務(wù)是iOS開發(fā)者的工作。

任務(wù)2也會在這份教程中簡略的提及,并且多數(shù)情況僅僅是為了測試目的。發(fā)送一個遠(yuǎn)程通知是App服務(wù)端的工作,并且這部分內(nèi)部會因為App的不同而不同。大多數(shù)App都會使用第三方服務(wù)(比如Parse。com或者Google ColoudMessaging)推送通知,其它的App或使用定制化的解決方案或使用比較流行的框架(比如: Houston)。

正式開始之,下載已經(jīng)準(zhǔn)備好的WenderCast開始工程。WenderCast是一個讓用戶獲取raywenderlich.com播客節(jié)目和時實消息的應(yīng)用。

在Xcode中打開WenderCast.xcodeproj簡單瀏覽一下。編繹運(yùn)行即可查看當(dāng)前最新播客節(jié)目:


1463988997846298.jpg

這個App的存在的問題是當(dāng)有新的播客節(jié)目可以獲取時不能通知到用戶。并且也不能顯示任何最新的消息。接下來你將用遠(yuǎn)程推送功能修復(fù)這個問題!

為App配置遠(yuǎn)程推送功能

推送通知需要較高的安全性。這點是非常重要的,因為你不會想讓其它人給你的用戶發(fā)送通知。這也就意味著要實現(xiàn)遠(yuǎn)程推送功能你必需跳過一些坑。

打開遠(yuǎn)程推送服務(wù)

第一步是更改App ID。在Xcode中進(jìn)入 App Settings -> General 把 Bundle Identifier 改為任意唯一的字符串。


1463989038763395.png

接下來你需要在你的開發(fā)者帳號下添加打開了推送通知功能的App ID。幸運(yùn)的是,Xcode有更簡單的方法實現(xiàn)這個步驟。進(jìn)入 App Settings -> Capabilities 把Push Notifications設(shè)置為 On。
在Xcode完成一些下載后,看起應(yīng)該會是下面的樣子


1463989064930009.png

這個步驟背后的操作是,如果你當(dāng)前的開發(fā)者帳號下沒有對應(yīng)的App ID就會主動創(chuàng)建App ID,并且打開推送通知功能。你可以登陸開發(fā)者中心確認(rèn)是否打開了這個功能:


1463989123284236.jpg

如果這個過程中出現(xiàn)問題,可以手動創(chuàng)建App ID或者點擊開發(fā)者中心 + 或 Edit 按鈕開啟推送通知功能。
以上就是你目前需要的配置。

注冊遠(yuǎn)程推送

注冊遠(yuǎn)程推送需要兩步。第一步,你必需向用戶請求推送通知許可,獲得許可之后才能注冊遠(yuǎn)程推送。如果所有步驟進(jìn)行順利,系統(tǒng)將會向你提供一個 device token,你可以把它認(rèn)為是當(dāng)前設(shè)備的”地址”。
在WenderCast應(yīng)用中你需要用在應(yīng)用啟動后立即注冊遠(yuǎn)程推送。
打開AppDelegate.swift,添加以下代碼到AppDelegate末尾。

 此處,我換成OC版本,原文是Swift代碼
 UIUserNotificationSettings *set =[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound) categories:nil];
[[UIApplication sharedApplication]registerUserNotificationSettings:set];
[[UIApplication sharedApplication]registerForRemoteNotifications];

這個方法創(chuàng)建了一個 UIUserNotificationSettings 實例對象并把它作為參數(shù)傳給 registerUserNotificationSettings(_:) 。UIUserNotificationSettings 存儲你的應(yīng)用將到用到的通知類型設(shè)置。

對于UIUserNotificationType的值你可以用下面幾個枚舉值的任意組合。

  • .Badge 允許App在圖標(biāo)上顯示角標(biāo)數(shù)字

  • .Sound 允許App播放聲音

  • .Alert 允許App顯示文本

UIUserNotificationCategory 是Set類型參數(shù)當(dāng)前暫時傳 nil,以允許你指定你的App能夠處理的不同類型的通知。當(dāng)你需要實現(xiàn)可交互的通知時,這樣的設(shè)置是必需的。后面的部分你將會用到可交互通知。

在 application(:didFinishLaunchingWithOptions:launchOptions:): 方法內(nèi)的第一行調(diào)用 registerForPushNotifications(:) :

func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions:[NSObject: AnyObject]?) -> Bool {
    registerForPushNotifications(application)
    //...
}

編繹運(yùn)行,當(dāng)App啟動時你會收到一個彈窗請求通知許可:

1463989267324436.jpg

點擊 OK,現(xiàn)在App可以顯示通知了。但是,如果用戶拒絕了發(fā)送通知的請求該應(yīng)怎么辦?

當(dāng)用戶接受或拒絕請求許可又或者之前做出過是否允許的選擇, UIApplicationDelegate 的一個代理方法將會被調(diào)用. 添加以下代碼到 AppDelegate:

func application(application: UIApplication,didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {

}

在這個方法中,你會接收到另一個 UIUserNotificationSettings 實現(xiàn)對象。這個實例對象與之前你之前所傳入的不同。你之前傳入的是你所希望的設(shè)置,而當(dāng)前這個是用戶當(dāng)前授權(quán)的設(shè)置。

在App每次啟動時都調(diào)用 registerUserNotificationSettings(:) 是相當(dāng)重要的。因為用戶在任何時候都有可能在設(shè)置應(yīng)用內(nèi)改變通知的授權(quán)許可。 application(:didRegisterUserNotificationSettings:) 方法會告訴你用戶當(dāng)前給你的App什么樣的授權(quán)許可。

現(xiàn)在第一步已經(jīng)完成,你可以注冊遠(yuǎn)程推送通知了。這一步相當(dāng)簡單,因為你不再需要向用戶請求什么許可了。用下面的代碼更新 application(_:didRegisterUserNotificationSettings:) 方法:

func application(application: UIApplication,didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
  if   notificationSettings.types != .None {
          application.registerForRemoteNotifications()
  }
}

在上面的方法中,首先檢查當(dāng)前用戶是否允許通知,如果允許直接調(diào)用registerForRemoteNotifications()。

其次,registerForRemoteNotifications()的請求注冊的返回狀態(tài)會通過 UIApplicationDelegate協(xié)議中的某些方法通知你。

添加以下代碼到 AppDelegate :


1463994202124520.png

就像方法名所暗示的那樣,當(dāng)注冊通知成功后系統(tǒng)會調(diào)用 application(:didRegisterForRemoteNotificationsWithDeviceToken:) 方法,否則將會調(diào)用 application(:didFailToRegisterForRemoteNotificationsWithError:)方法。

當(dāng)前 application(_:didRegisterForRemoteNotificationsWithDeviceToken:) 方法的實現(xiàn)看起來難以理解,其實它僅僅只是獲取 deviceToken 然后轉(zhuǎn)換成字符串。deviceToken的值就是這個過程得到的結(jié)果。它是由APNs服務(wù)器提供用來標(biāo)識當(dāng)前設(shè)備當(dāng)前App。當(dāng)發(fā)送時推送通知的時候,App用deviceToken作為“地址”傳遞到當(dāng)前設(shè)備。

# 打印出 deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
{
    NSString *deviceTokenString2 = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""]
                                     stringByReplacingOccurrencesOfString:@">" withString:@""]
                                    stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"方式2:%@", deviceTokenString2);
}

注意:會有很多原因?qū)е伦允 W畛E龅皆蚴浅绦蜻\(yùn)行在模擬器上,或者App ID設(shè)置不正確。具體原因打印error值會提供更加詳細(xì)的信息。

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error ;
{
     NSLog(@"%@",error);
}

到此,編繹運(yùn)行。確保你當(dāng)前運(yùn)行在真機(jī)上,你將會在控制臺看到打印出的device token。下面將會是你看到的結(jié)果:


1463989410955146.png

把device token復(fù)制到某處保存。

在正式發(fā)送通知之前你還需要一點點配置,所以回到開發(fā)者中心。

創(chuàng)建一個SSL證書和PEM文件

在開發(fā)者中心進(jìn)入 Certificates, Identifiers & Profiles -> Identifiers -> App IDs 找到你應(yīng)用的App ID.在 Application Services 下面 Push Notifications 應(yīng)該為 Configurable :

1463989437850933.png

點擊 Edit 滾動到 Push Notifications:


1463989449361471.png

在 Development SSL Certificate 欄下,點擊 Create Certificate… 接下來的步驟就是創(chuàng)建 CSR 文件。創(chuàng)建好CSR文件后點擊 continue 和 Generate,這步會用你創(chuàng)建的CSR文件生成證書。最后下載并運(yùn)行生成好的證書,證書將被添加到你的鑰匙串應(yīng)用中,并與私鑰成對。


1463989539559130.png

在開發(fā)者中心,你的App ID現(xiàn)在推送通知功能在development下應(yīng)該處于Enable狀態(tài)。


1463989559290885.png

在關(guān)閉鑰匙串應(yīng)用前還有最后一件事,右擊你剛才添加的證書,選擇 Export :


1463989597273139.png

保存在桌面并命名為WenderCastPush.p12。


1463989632581691.png

你會被提示要求為你的.p12文件設(shè)置密碼,你可以選擇不輸或者輸入一個你想設(shè)置的密碼。這里我用”WenderCastPush”作為密碼。接下來你需要輸入電腦登陸密碼來允許導(dǎo)出p12文件。

接下來,打開你的終端并執(zhí)行以下命令來從p12文件生成PEM文件:

$ cd ~/Desktop
$ openssl pkcs12 -in WenderCastPush.p12 -out WenderCastPush.pem -nodes -clcerts

如果你導(dǎo)出p12文件時輸入了密碼,在這里你必須輸入相同的密碼。

到此為止,你已經(jīng)艱難的躍過了很多坑,這一切都是值得的。接下來你將用你生成的WenderCastPush.pem文件發(fā)送第一個通知。

發(fā)送通知

之前下載的開始工程會包含一個WenderCastPush文件;里面包含兩個用于發(fā)送通知簡單腳本。你需要用到的是newspush.php。正如文件名所暗示的,這個腳本將會向你的用戶發(fā)送一個彈窗通知消息。

發(fā)送推送通知需要和APNS建立SSL連接,SSL連接是用之前創(chuàng)建的證書進(jìn)行加密。這就是為什么要生成 WenderCastPush.pem 文件。重命名 WenderCastPush.pem 為 ck.pem,并且替換掉當(dāng)前已經(jīng)存在于 WenderCastPush 文件夾下的 ck.pem 文件。

打開 newspush.php 并更新之前接收到的 $deviceToken 和導(dǎo)出文件時輸入的密碼 $passphrase

// Put your device token here (without spaces):

$deviceToken = '43e798c31a282d129a34d84472bbdd7632562ff0732b58a85a27c5d9fdf59b69'

// Put your private key's passphrase here:
$passphrase = 'WenderCastPush'

打開終端,cd 到 newspush.php 所在的文件夾,輸入:

php newspush.php 'Breaking News' 'https://raywenderlich.com'

如果進(jìn)行順利,你的終端將會顯示:

Connected to APNS
Message successfully delivered

現(xiàn)在,你應(yīng)該會收到你的第一條通知:


1463989700574992.jpg

注意:如果你的App被打開并處于前臺運(yùn)行狀態(tài),你將看不到任何東西。通知已經(jīng)被投送但是App還不會處理這個通知。你只需要簡單的關(guān)閉App并重新發(fā)送通知即可。

常見問題
也許你會遇到以下問題:

  • 只能接收到部分通知:如果你同時發(fā)送多個通知,只有部分通知將會被接收,不用擔(dān)心!這正是我們想要的結(jié)果。當(dāng)發(fā)送通知時APNS會為每一個開啟了推送通知的設(shè)備保持一個高質(zhì)量服務(wù)(Quality of Service)隊列。這個隊列的大小是1,所以如果你同時發(fā)送多個通知,最后一個通知才會被發(fā)送。

  • 連接到APNS出現(xiàn)問題:出現(xiàn)這個問題的原因可能是你的防火墻阻塞了APNS所使用的端口。所以確保你的防火墻沒有阻塞住這些端口。另一個可能的原因是私鑰和CSR文件不正確。記住,每一個App ID有一個唯一的CSR和配對的私鑰。

解剖推送通知的基本原理

在進(jìn)行任務(wù)3之前,需要理解一下你推送的通知,打開 newspush。php 文件理解發(fā)送一個通知的基本概念應(yīng)該是怎么樣的。
注意第32-40行,這就是用JSON格式編碼的裝載體。這就是實際上發(fā)送給APNS的東西。在我們當(dāng)前的例子中,裝載體像下面一樣:

Paste_Image.png

對于一個不懂JSON數(shù)據(jù)的人來說,用{}括起來的塊相當(dāng)于一個字典類型的數(shù)據(jù)。

這個裝載體是一個至少包含一項內(nèi)容的字典,這項內(nèi)容就是 aps, 它本身也是一個字典。在這個例子中”aps”包含”alert”,”sound”和”link_url”等字段。當(dāng)接收到一個通知,就會顯示一個包含”Breaking News!”文本的提醒視圖,并且有標(biāo)準(zhǔn)的提醒音效。

“l(fā)ink_url”實際上是一個自定義的字段。你可以添加類似的自定義字段到裝載體中,并且它會被投送到你的應(yīng)用。因為你并沒有在應(yīng)用中處理這個字段,所以當(dāng)前接收到這個鍵值對會什么都不做。

你可以在aps字典中添加以下5個鍵(key):

  • alert。這個字段可以是一個字符串,就像當(dāng)前的例子。或是是一個字典。如果是一個字典,可以是本地化的文本或者通知的其它部分。查看蘋果文檔所支持的key。

  • badge。這是一個將被顯示在應(yīng)用圖標(biāo)上的數(shù)字。你可以設(shè)置這個鍵為0來清除角標(biāo)。

  • sound。通過設(shè)置這個建,你可以播放存放在App本地定制的通知提示音來取代系統(tǒng)默認(rèn)的通知提示音。定制的通知提示音必須在30秒以內(nèi)并且還有一些其它的限制,你可以查看蘋果文檔了解更詳細(xì)信息。

  • content-available。設(shè)置這個鍵為1,當(dāng)前通知會變成靜默通知。這個部分會在這份教程的后面部分探索。

  • category。這個鍵定義了通知的分類,用于顯示定制通知所包含的交互行為。同樣,接下來會探索這部分的內(nèi)容。

除此之外,你可以添加任意你想要添加的定制化數(shù)據(jù),只要裝載體不超過4096個字節(jié)。

如果你玩夠了推送通知,接下來我們進(jìn)入到下一個章節(jié)。

處理接收到的通知

在這個章節(jié),你將會學(xué)習(xí)當(dāng)App接收到通知后或者用戶點擊了通知應(yīng)該如何執(zhí)行什么樣的操作。

當(dāng)你接收到一個通知后會發(fā)生什么

當(dāng)你的App接收到一個通知,UIApplicationDelegate 的一個方法將會被調(diào)用。

需要根據(jù)接到收通知時App所處的狀態(tài)的進(jìn)行不同的處理。

  • 如果你的應(yīng)用當(dāng)前不在運(yùn)行,并且用戶通過點擊推送通知啟動應(yīng)用,通知內(nèi)容會通過 application(_:didFinishLaunchingWithOptions:) 方法的 launchOptions 參數(shù)進(jìn)行傳遞。

  • 如果你應(yīng)用當(dāng)前正運(yùn)行在前臺,推送通知將不會被顯示。但是 application(_:didReceiveRemoteNotification:) 會被立即調(diào)用。

  • 如果你的應(yīng)用正在運(yùn)行,或者被掛起在后臺,并且用戶通過點擊通知使應(yīng)用進(jìn)入前臺 application(_:didReceiveRemoteNotification:) 方法會被調(diào)用。

在第一種情況下,WenderCast將到創(chuàng)建一個新的section,并直接打開以顯示到這個新建section。添加以下代碼到 application(_:didFinishLaunchingWithOptions:) 的末尾return語句之前。

// Check if launched from notification

// 1

if  let notification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [String: AnyObject] {

// 2 
let aps = notification[  "aps"  ] as! [String: AnyObject]
createNewNewsItem(aps)

// 3
(window?.rootViewController as? UITabBarController)?.selectedIndex = 1
}

這段代碼做了以下3件事:

檢查 UIApplicationLaunchOptionsRemoteNotificationKey 鍵對應(yīng)的值是否存在,如果存在,這個值應(yīng)該就是你發(fā)送的通知裝載體。

如果存在,獲取 aps 對應(yīng)字典并傳給 createNewNewsItem(_:) 方法,這個方法根據(jù)接收的字典創(chuàng)建一個 NewItem,并刷新表格。

改變tab控制器當(dāng)前選中的tab索引值為1,也就是直接顯示新聞控制器視圖。

為了測試這部分代碼,你需要編輯WenderCast的scheme:


1463990007399456.png

在 Run -> Info 下選擇 Wait for executable to be launched:


1463990002675410.png

這個選項會使調(diào)試器等待應(yīng)用程序安裝直到應(yīng)用程序第一次被啟動。
編繹運(yùn)行,完成安裝后,發(fā)送一些新的動態(tài)。點擊通知以啟動App,啟動之后App會顯示一些新消息。
1463990027360933.jpg

注意 如果你突然接收不到通知,最有可能的原因是device token被改了。如果你刪除應(yīng)用再重新安裝就有可能出現(xiàn)這種情況。確保你的device token是正確的。

為了處理另外兩種情況,添加以下代碼到 AppDelegate:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {

let aps = userInfo["aps"] as! [String: AnyObject]
createNewNewsItem(aps)
}

這個方法直接創(chuàng)建了一個新的 NewsItem。現(xiàn)在你可以把scheme設(shè)置回自動啟動App。
編繹運(yùn)行。保持App運(yùn)行在前臺,并選中新聞頁。發(fā)送一個通知,你可以看到消息奇跡般的顯示在視線內(nèi)。

1463990072111969.jpg

就是這樣!你的App現(xiàn)在可以處理基本的推送消息。

一些需要注意的事情:很多情況推送通知可能會被遺漏。對于WenderCast應(yīng)用來說是沒有問題的,因為裝滿消自己的列表對這個應(yīng)用來說并不是那么重要,但是一般來講你不應(yīng)該把推送通知做為傳遞內(nèi)容的唯一方式。作為備選項,推送通知應(yīng)該僅僅只是指示當(dāng)前有新的內(nèi)容可以獲取并讓App從服務(wù)器下載這些新的內(nèi)容。WenderCast應(yīng)用在這方有一些局限性,因為它并沒有合適的服務(wù)端。

可交互的通知

可交互的通知允許你添加定制化的按鈕在通知上。你也許注意到郵件通知或者Twitter消息通知有一個讓你回復(fù)或者點贊的部位。

可交互的通知是你通過注冊通知時設(shè)置 categories 定義的.每一個通知分類都可以有多個預(yù)先自定義的交互。

一旦完成注冊,就可以發(fā)送這個分類的通知.當(dāng)接收到通知相應(yīng)的交互就可以被用戶獲取。

對于 WenderCast 應(yīng)用,你將定義一個自定義”View”動作的”News”分類,自定義”View”允許用戶選擇查看,如果用戶選擇就會在App中直接顯示對應(yīng)的消息詳細(xì)文章。

添加以下代碼到 registerForPushNotifications(_:): 的開頭。

let viewAction = UIMutableUserNotificationAction()

viewAction.identifier = "VIEW_IDENTIFIER"
viewAction.title = "View"
viewAction.activationMode = .Foreground

這段代碼創(chuàng)建了一個按鈕標(biāo)題名為”View”的新交互通知,當(dāng)交互通知被用戶觸發(fā)時打開App并讓其進(jìn)入前臺.這個交互動作的標(biāo)識符是 VIEW_IDENTIFIER ,這個標(biāo)識符被用于區(qū)分同一通知的不同交互動作.
添加以下人碼片段至前面代碼之后:

let newsCategory = UIMutableUserNotificationCategory()
newsCategory.identifier = "NEWS_CATEGORY"
newsCategory.setActions([viewAction], forContext: .Default)

這段代碼定義了一個新通知分類,設(shè)置交互動作為之前定義的”View”動作,設(shè)置標(biāo)識符為” NEWS_CATEGORY”,這個標(biāo)識符你是裝載體要包含的內(nèi)容以用其指示當(dāng)前通知屬于哪個分類.

最后,通過以下代碼,把新建分類傳遞給UIUserNotificationSettings構(gòu)造方法。

let notificationSettings = UIUserNotificationSettings(forTypes: [.Badge, .Sound, .Alert], categories: [newsCategory])

編繹運(yùn)行,應(yīng)用會注冊新通知設(shè)定。按Home鍵來退出當(dāng)前應(yīng)用,以使推送通知能夠顯示。

在你再次運(yùn)行 newspush.php 之前,首先對指定的分類做一個改動。打開 newspush.php 修改通知裝載體使它包含通知的分類標(biāo)識符:

$body['aps'] = array(
  'alert'  => $message,
  'sound' => 'default', 
  'link_url' => $url,
  'category' => NEWS_CATEGORY', 
);

保存并關(guān)閉newspush.php,然后運(yùn)行以發(fā)送通知。如果一切進(jìn)展順利,你可以下拉并輕掃顯示的通知你會看到View按鈕被顯示。

1463990140648178.jpg

非常好,點擊”View”按鈕將啟動WenderCast但不會做任何事情。為了獲取通知裝載體顯示新的內(nèi)容項,你需要在代理方法中做更多的操作。

處理通知交互動作事件

回到 AppDelegate.swift,添加另一個方法:

  func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], completionHandler: () -> Void) {

// 1 
let aps = userInfo["aps"] as! [String: AnyObject]

// 2
if  let newsItem = createNewNewsItem(aps) {

(window?.rootViewController as? UITabBarController)?.selectedIndex = 1

// 3   
if   identifier == "VIEW_IDENTIFIER",
 let url = NSURL(string: newsItem.link) {
let safari = SFSafariViewController(URL: url)

window?.rootViewController?.presentViewController(safari, animated: true, completion: nil)    

}
}

// 4
completionHandler()
}

當(dāng)用戶通過通知的交互動作打開應(yīng)用時這個方法將會被調(diào)用.這看來起好像做了很多事,但是實際上沒有多少新的東西.這段代碼做了以下事情:

  • 獲取 aps 字典。
  • 根據(jù)獲取到的字典創(chuàng)建 NewItem 并跳到新聞頁。
  • 檢查以 identifier 為參數(shù)傳進(jìn)來的交互動作的標(biāo)識符。如果View交互動作的標(biāo)識符和鏈接有效則用。SFSafariViewController 顯示這個鏈接內(nèi)容。
  • 在處理完用戶交互動用之后調(diào)用系統(tǒng)傳遞給你的 completionHandler 回調(diào)。
  • 編繹運(yùn)行,退出App。發(fā)送通知。但請確保下面的URL中有效的:
  $ php newspush.php  'New Posts!'   'https://raywenderlich.com'

點擊通知的交互動作,在WenderCast應(yīng)用啟動后會立即展示Safari控制器。

1463990244582650.jpg

恭喜,你剛剛已經(jīng)完成了可交互通知的實現(xiàn)!嘗試多發(fā)送幾次通知,并用不同的方法打開通知觀察通知的展現(xiàn)行為。

靜默推送通知

靜默推送通知可以靜默方式的喚醒你的App并讓它在后臺執(zhí)行任務(wù)。WenderCast可以利用這個特性悄悄地刷新播客列表。

正如你所想象的,配合合適的服務(wù)端這個功能會非常有用。你不需要不斷的主動獲取數(shù)據(jù),當(dāng)有數(shù)據(jù)可獲取時僅僅只需要發(fā)送一個靜默通知。

開始之前進(jìn)入 App Settings -> Capabilites 并打開 WenderCast的 Background Modes. 檢查最后一個選項,Remote Notifications 是否勾選。

1463990284465137.png

現(xiàn)在你的App接收到某個靜默通知就可以在后臺喚醒.

在AppDelegate內(nèi),用下面更強(qiáng)大的版本替換 application(_:didReceiveRemoteNotification:) 方法:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {

let aps = userInfo["aps"] as! [String: AnyObject]

// 1
if (aps["content-available"] as? NSString)?.integerValue == 1 {

// Refresh Podcast

// 2  
let podcastStore = PodcastStore.sharedStore
podcastStore.refreshItems { didLoadNewItems  in

 // 3      
  completionHandler(didLoadNewItems ? .NewData : .NoData)
    } 
} 
else
{
    // News
    // 4
  createNewNewsItem(aps)
  completionHandler(.NewData)

    }
}

這段代碼:

  • 檢查 content-available 是否為1,以確定是否是靜默推送。
  • 刷新播客列表,因為需要訪問網(wǎng)絡(luò)所以刷新列表是異步的。
  • 當(dāng)刷新完列表,調(diào)用 completionHandler 回調(diào)方法,讓系統(tǒng)知道數(shù)據(jù)是否已經(jīng)下載。
  • 如果不是靜默通知,假定它是消息并創(chuàng)建一個新的消息項。

必需要確保 completionHandler(_:) 方法被調(diào)用并傳遞真實的是否獲取到數(shù)據(jù)的結(jié)果。系統(tǒng)會根據(jù)回調(diào)計算耗電量和App在后臺的時間,系統(tǒng)會根據(jù)需要調(diào)節(jié)App的耗電量以及在后臺的時間。

以上就是這段代碼所做的事。現(xiàn)在你可以用 contentpush.php 給你的應(yīng)用發(fā)送一個靜默通知。請務(wù)必確認(rèn)以下設(shè)置腳本的正確性:

// Put your device token here (without spaces):
  $deviceToken = '43e798c31a282d129a34d84472bbdd7632562ff0732b58a85a27c5d9fdf59b69'
;
// Put your private key's passphrase here:
$passphrase = 'WenderCastPush'  ;

在終端直接運(yùn)行:

$ php contentpush.php

如果一切順利,什么事都不會發(fā)生。為了看到這段代碼的運(yùn)行結(jié)果,與之前設(shè)置的一樣結(jié)果必須把scheme設(shè)置為”Wait for executable to be launched”并在 application(_:didReceiveRemoteNotification:fetchCompletionHandler:) 方法旁邊打上斷點,以確認(rèn)這個方法會被調(diào)用。

路在何方?

恭喜你已經(jīng)完成了這份推送通知教程的內(nèi)容并且WenderCast應(yīng)用也有全部的推送功能!

你可以在這里下載完整的工程。記住為了能讓工程正常運(yùn)行你仍然需要更改Bundle ID和證書。

推送通知功能對于現(xiàn)在的App已經(jīng)是一個不可或缺的部分,但如果你發(fā)送的通知太頻繁用戶仍然會調(diào)整你的通知請求許可。對于一個深思熟慮的設(shè)計,推送通知會讓你的應(yīng)用保持足夠的用戶粘性!

這只貓接收到“推送通知”后它就知道晚餐已經(jīng)準(zhǔn)備好了。

我希望你能喜歡這份推送教程。如果你有任何問題,你可以在下面的評論中隨意提問。


原文鏈接
iOS 10 之前的推送之遠(yuǎn)程推送(iOS Notification Of Remote Notification)這篇文章也不錯

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 版權(quán)聲明 本文翻譯自:raywenderlich.com 原文作者: Jack Wu 譯者: JMStack 轉(zhuǎn)載...
    jmstack閱讀 7,206評論 6 30
  • 極光推送: 1.JPush當(dāng)前版本是1.8.2,其SDK的開發(fā)除了正常的功能完善和擴(kuò)展外也緊隨蘋果官方的步伐,SD...
    Isspace閱讀 6,758評論 10 16
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,666評論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,786評論 18 139
  • Day26 170703 教皇
    蝸子閱讀 114評論 0 0