如何在iOS 10中使用推送通知
譯文簡介
雖然經(jīng)常被過度使用,但是推送通知確實是一種有效的吸引用戶注意力的方式,例如通知他們更新軟件或需要采取相應的措施,等等。當前,新的iOS 10系統(tǒng)在推送通知方面也提供了新的支持,例如新消息、優(yōu)惠和時間表變化等。
在本教程中,你將學習如何在你的iOS應用程序中使用推送通知,同時還向你展示iOS 10的一些新功能。為了開發(fā)iOS 10推送通知,你需要使用Xcode 8Beta版本。
起步
啟用推送通知在Xcode中是很容易的,請遵循如下幾個步驟:
1.啟動Xcode創(chuàng)建一個新項目,給它一個唯一的名稱和相應的捆綁標識符。
2.創(chuàng)建項目后,轉到【Project Settings】界面,選擇【Capabilities】選項卡。然后,啟動推送通知功能,如下圖所示。
【注意】如果你是蘋果開發(fā)者計劃的一位付費會員,你只會看到【Push Notifications】(推送通知)功能項。
接下來,請轉到【Developer Account】部分并檢查Xcode自動作出的更改。從左邊的菜單中選擇【Certificates, IDs & Profiles】,然后在【Identifiers】部分選擇【App IDs】。找到剛才創(chuàng)建的應用程序名稱并選中,以便顯示相應的服務列表。
【注意】在【Push Notifications】附近有兩個可配置狀態(tài)。
先不要關閉此屏幕,你將很快返回到這個界面的。
發(fā)送通知
在本文中,我將使用Pusher技術(https://github.com/noodlewerk/NWPusher/releases/tag/0.7.0)發(fā)送推式通知。其實,你還可以使用其他解決方案,如Houston技術(https://github.com/nomad/houston)。無論采取哪種方式,想發(fā)送通知你都需要使用證書。
為了創(chuàng)建一個證書,你需要打開【Keychain Access】訪問權限并選擇“Keychain Access -> Certificate Assistant -> Request a Certificate from a Certificate Authority”菜單項。
填寫如下圖所示的表格并單擊【Continue】按鈕。請確保你剛才的選項保存到磁盤上。
現(xiàn)在,再返回到【Developer Account】屏幕,你可以在【App IDs】處生成用于開發(fā)或部署的證書了。選擇對應的應用程序后,在底部單擊【Edit】命令。然后,在【Push Notifications】部分,單擊【Create Certificate for development】。
必要時,你需要上傳由鑰匙串(Keychain)生成的證書請求,然后點擊【Continue】按鈕。請參考下圖。
你現(xiàn)在已經(jīng)創(chuàng)建了證書,并可以下載它。為了安裝它,請打開下載的文件。
現(xiàn)在,你可以下載并運行Pusher。
【注意】在窗口頂部的組合框中要求選擇一個推送證書(Push Certificate)。因為它位于你的鑰匙串中,OS X將詢問是否允許訪問該證書。
上面圖的第二個字段(注意那個內容顯灰色的下拉列表框控件)需要你輸入一個設備令牌,你會在下一步中得到這個數(shù)據(jù)的。
獲取通知
從現(xiàn)在開始,你需要編寫代碼了。將接收通知的設備必須注冊到蘋果推送通知服務(Apple Push Notification Service,簡稱“APNS”)。為此,你需要發(fā)送一個在應用程序啟動時生成的唯一的令牌。
接下來,請打開文件AppDelegate.swift,然后添加下面的方法。
【注意】此代碼包括中使用了最新的Swift 3.0語法;因此,有些語法可能不同于你以前熟悉的2.0格式。
- func registerPushNotifications() {
- DispatchQueue.main.async {
- let settings = UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil)
- UIApplication.shared().registerUserNotificationSettings(settings)
- }
- }
在這里的設置中,你需要指定應用程序將接收的類型(稍后會介紹)。在應用程序啟動時調用此方法。
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
- registerPushNotifications()
- return true
- }
此時,應用程序將自動顯示一個彈出窗口,要求用戶通過相應的權限來發(fā)送通知。
只有在用戶同意它時,才能注冊并發(fā)送該通知。其中,UIApplicationDelegate方法負責處理響應的問題。
- func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
- if notificationSettings.types != UIUserNotificationType() {
- application.registerForRemoteNotifications()
- }
- }
在上述代碼中,首先檢查用戶是否已授予權限,然后調用方法來注冊遠程通知。當請求完成時,后者將調用另一個委托方法。注意到,響應消息中包含一個設備令牌(你可以在調試階段輸出有關內容)。當發(fā)送推式通知來標識設備時,你將需要此令牌。
- func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
- let chars = UnsafePointer<CChar>((deviceToken as NSData).bytes)
- var token = ""
- for i in 0..<deviceToken.count {
- token += String(format: "%02.2hhx", arguments: [chars[i]])
- }
- print("Registration succeeded!")
- print("Token: ", token)
- }
如果出現(xiàn)了錯誤,則調用下面的方法。
- func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
- print("Registration failed!")
- }
【注意】在啟動應用程序時調用registerUserNotificationSettings方法是很重要的,因為用戶有可能更改其設置的權限。此外,RegisterForRemoteNotifications方法也很重要,因為有些情況下設備令牌可以更改并且將不再發(fā)送通知。
到目前為止,你的上述設置足以能夠接收一個簡單的通知了。
通知有效載荷
一個應用程序可以通過若干種不同方法來接收通知。這只需要在通知的有效載荷部分指定即可,其中包含應用程序如何通知用戶以及你可以使用通知發(fā)送的自定義數(shù)據(jù)。
通知實際上是發(fā)送給用戶的一個JSON字典,它本身又包含了一個帶有aps鍵的字典。在這第二個詞典中,你可以指定有效載荷部分的鍵/值對。
最常見的數(shù)據(jù)有:
向用戶顯示的通知消息。這可以是一個簡單的字符串或一個帶有如標題、正文等鍵的字典。
設備收到通知時將播放的聲音。它可以是應用程序自定義的聲音或系統(tǒng)聲音。
應用程序在其圖標附近將用作徽章的一個數(shù)字。將此設置為0將會刪除徽章。
content-available:值為1時將一個無聲通知發(fā)送給用戶。此時,不會播放任何聲音或設置任何徽章數(shù)字,但它會喚醒應用程序以便可以與服務器通信。
本教程的其余部分中將使用的通知內容如下:
- {
- "aps": {
- "alert": {
- "title":"Hello! :)",
- "body":"App closed..."
- },
- "badge":1,
- "sound":"default"
- }
- }
應用程序生命周期
把Xcode控制臺中顯示的設備令牌復制到Pusher。然后,將上一小節(jié)中的JSON對象復制到有效載荷文本字段(即下圖最下面的文本框)。
現(xiàn)在,你可以試著推送第一次通知。如果設備的屏幕被鎖定,應當看起來如下面這樣。但是,當用戶選擇視圖時什么也沒有。
為了處理通知,你還需要添加另外幾個新的方法,有關代碼如下:
- private func getAlert(notification: [NSObject:AnyObject]) -> (String, String) {
- let aps = notification["aps"] as? [String:AnyObject]
- let alert = aps?["alert"] as? [String:AnyObject]
- let title = alert?["title"] as? String
- let body = alert?["body"] as? String
- return (title ?? "-", body ?? "-")
- }
如果結構是相同的,這段代碼將返回收到的通知中的標題和正文內容。
- func notificationReceived(notification: [NSObject:AnyObject]) {
- let viewController = window?.rootViewController
- let view = viewController as? ViewController
- view?.addNotification(
- title: getAlert(notification: notification).0,
- body: getAlert(notification: notification).1)
- }
此方法會將一個新行添加到應用程序主視圖(參見項目完整的ViewController代碼)中的UITableView中。
我通過如下三種情形測試了推送通知的使用情況。
當應用程序關閉時
如果用戶從通知中打開應用程序,那么將調用經(jīng)修改的如下所示的 didFinishLaunchingWithOptions方法:
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
- // Override point for customization after application launch.
- application.applicationIconBadgeNumber = 0; // Clear badge when app launches
- // Check if launched from notification
- if let notification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [String: AnyObject] {
- window?.rootViewController?.present(ViewController(), animated: true, completion: nil)
- notificationReceived(notification: notification)
- } else {
- registerPushNotifications()
- }
- return true
- }
上面代碼中,在假設用戶已經(jīng)看到通知的情況下清除徽章。然后,檢查應用程序是通過圖標還是使用通知方式打開的。在第一種情況下,調用registerPushNotifications()方法并繼續(xù)遵循以前的流程進行。如果是通過通知方式運行的應用程序,那么將調用自定義的notificationReceived方法并添加一個新行。
當應用程序處于前臺時
如果用戶在使用應用程序,即應用程序正處在前臺,那么可以使用下列方法來處理通知。此方法將把通知添加到tableView視圖中:
- func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
- notificationReceived(notification: userInfo)
- }
【注意】在這種情況下,通知是不會播放聲音。
當應用程序處于后臺時
在這種情況下,我添加了一個方法來清除徽章編號。通知的處理方式與應用程序處于前臺時一樣。
- func applicationWillEnterForeground(_ application: UIApplication) {
- application.applicationIconBadgeNumber = 0; // Clear badge when app is or resumed
- }
最后,表格中將顯示對應于所有通知信息的一共三行內容;請參考下面的圖形。
小結
在iOS 10中,推送通知支持對于程序員們來說又會是一個非常有趣的機會,因為它可以提供在以前版本中根本無法使用的不同級別的交互方式。最后,我希望本文能夠為你在自己的應用程序中使用推送通知提供很好的借鑒作用。