Swift-本地通知和遠(yuǎn)程通知

指推送通知跟NSNotification有區(qū)別:

1、NSNotification是系統(tǒng)內(nèi)部發(fā)出通知,一般用于內(nèi)部事件的監(jiān)聽(tīng),或者狀態(tài)的改變等等,是不可見(jiàn)的
2、本地通知與遠(yuǎn)程通知是可見(jiàn)的,主要用于告知用戶或者發(fā)送一些App的內(nèi)容更新,推送一些相關(guān)的消息,讓用戶知道App內(nèi)部發(fā)生了什么事情。

通知的注意點(diǎn)

1、App在前臺(tái)運(yùn)行的時(shí)候,通知不會(huì)展示出來(lái)
2、點(diǎn)擊通知,默認(rèn)會(huì)自動(dòng)打開(kāi)推送通知的App
3、不管App是否打開(kāi),通知都可以如期發(fā)出

1. 什么是本地推送通知

不需要聯(lián)網(wǎng)就可以發(fā)出的通知

使用場(chǎng)景:

提醒用戶完成一些任務(wù),比如:定時(shí)提醒,生活備注,看電影等等

推送通知屬性:
// 枚舉值-發(fā)出通知的時(shí)間(有局限性)
@property(nonatomic) NSCalendarUnit repeatInterval;
// 自定義-發(fā)出通知的時(shí)間(可以自由設(shè)定時(shí)間)
@property(nonatomic,copy) NSCalendar *repeatCalendar;
// 區(qū)域-創(chuàng)建只需要?jiǎng)?chuàng)建一個(gè)中心點(diǎn)與半徑就可以了
@property(nonatomic,copy) CLRegion *region
// 進(jìn)入?yún)^(qū)域發(fā)出一個(gè)通知,設(shè)置yes,只會(huì)發(fā)出一個(gè)通知,設(shè)置NO就會(huì)每次進(jìn)入這個(gè)區(qū)域都發(fā)送
@property(nonatomic,assign) BOOL regionTriggersOnce NO
// 設(shè)置通知的內(nèi)容
@property(nonatomic,copy) NSString *alertBody;      
 // 決定alertAction是否生效
@property(nonatomic) BOOL hasAction;
// 設(shè)置滑塊的文字
@property(nonatomic,copy) NSString *alertAction;    

// 設(shè)置點(diǎn)擊通知的啟動(dòng)圖片(一般設(shè)置App啟動(dòng)圖片后,這里可以隨便寫)
@property(nonatomic,copy) NSString *alertLaunchImage;
// 設(shè)置alertTitle,就是通知內(nèi)容上面的文字
@property(nonatomic,copy) NSString *alertTitle
 // 設(shè)置彈出的聲音
@property(nonatomic,copy) NSString *soundName;
 // 設(shè)置App的消息條數(shù)
@property(nonatomic) NSInteger applicationIconBadgeNumber;
 // 設(shè)置通知一些額外數(shù)據(jù)
 @property(nonatomic,copy) NSDictionary *userInfo;
如何發(fā)出本地通知:
//發(fā)出一個(gè)電池電量為100的本地通知
let alertBody = "電池電量通知"
let localNotify = UILocalNotification()
localNotify.alertBody = alertBody
localNotify.soundName = UILocalNotificationDefaultSoundName
localNotify.userInfo = ["battery": 100]
UIApplication.shared.presentLocalNotificationNow(localNotify)

使用注意:
iOS7,不需要用戶授權(quán)就可發(fā)出通知,而iOS8以后,必須用戶授權(quán)才可以發(fā)出通知

//申請(qǐng)授權(quán)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        guard #available(iOS 10, *) else {
            // 請(qǐng)求授權(quán)
            let typeValue = UIUserNotificationType.alert.rawValue |
                UIUserNotificationType.badge.rawValue |
                UIUserNotificationType.sound.rawValue
            let type = UIUserNotificationType(rawValue: typeValue)
            let setting = UIUserNotificationSettings(types: type, categories: nil)
            UIApplication.shared.registerUserNotificationSettings(setting)
            
            // 發(fā)送請(qǐng)求
            UIApplication.shared.registerForRemoteNotifications()
            return
        }
        let typeValue = UNAuthorizationOptions.alert.rawValue |
            UNAuthorizationOptions.badge.rawValue |
            UNAuthorizationOptions.sound.rawValue
        UNUserNotificationCenter.current().requestAuthorization(options: UNAuthorizationOptions(rawValue: typeValue)) { (granted, error) in
            if granted { // 同意
                UIApplication.shared.registerForRemoteNotifications()
            } else { // 拒絕
                /// 彈出提示框
            }
        }
}

監(jiān)聽(tīng)通知,如果用戶打開(kāi)通知,可以讓用戶進(jìn)入一些特定的界面

func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
    NSLog(notification)
    guard let userInfo = notification.userInfo else {
        return
    }
    //處理通知
}
2. 什么是遠(yuǎn)程推送通知

<1>從遠(yuǎn)程服務(wù)器推送給客戶端的通知,需要連接網(wǎng)絡(luò)
<2>遠(yuǎn)程推送服務(wù),又稱為APNs 蘋果推送通知服務(wù)(Apple Push Notification services)
<3>模擬器無(wú)法調(diào)試遠(yuǎn)程推送

傳統(tǒng)推送通知

傳統(tǒng)推送通知是相對(duì)于APNs而言的,傳統(tǒng)推送通知的原理是:當(dāng)APP打開(kāi)時(shí)和App的服務(wù)器建立一個(gè)長(zhǎng)連接(需要網(wǎng)絡(luò)),當(dāng)需要通知的時(shí)候,App服務(wù)器通過(guò)長(zhǎng)連接向?qū)?yīng)的客戶端發(fā)送數(shù)據(jù),當(dāng)客戶端接收到數(shù)據(jù)時(shí)使用UILocalNotfication本地通知的方式來(lái)展示,這樣就實(shí)現(xiàn)了傳統(tǒng)推送通知。

傳統(tǒng)推送通知必須要聯(lián)網(wǎng),如果關(guān)閉了App或者打開(kāi)了App但是無(wú)法連接服務(wù)器了,這些情況都收不到通知了。

APNs

所有蘋果設(shè)備在聯(lián)網(wǎng)狀態(tài)下都會(huì)與蘋果服務(wù)器建立長(zhǎng)連接,連接是雙向的,蘋果設(shè)備可以向蘋果服務(wù)器發(fā)送請(qǐng)求,蘋果服務(wù)器也可以向蘋果設(shè)備發(fā)送請(qǐng)求。

蘋果服務(wù)器常用的通知功能:

<1>時(shí)間校準(zhǔn)
<2>系統(tǒng)升級(jí)
<3>查找我的iPhone
長(zhǎng)連接的好處:更加及時(shí)

為什么需要遠(yuǎn)程推送通知:

解決獲取傳統(tǒng)數(shù)據(jù)的局限性,讓數(shù)據(jù)實(shí)時(shí)更新

使用場(chǎng)景:

聊天功能(一般非即時(shí)聊天)、推送一下App的內(nèi)部新功能、版本下載等

注:所有的蘋果設(shè)備,在聯(lián)網(wǎng)狀態(tài)下,都會(huì)與蘋果的服務(wù)器建立-長(zhǎng)連接

遠(yuǎn)程通知的過(guò)程:

例如微信App:首先每個(gè)聯(lián)網(wǎng)并打開(kāi)微信的App都與微信服務(wù)器有一個(gè)長(zhǎng)連接,當(dāng)微信A用戶向微信B用戶發(fā)送一個(gè)消息時(shí),微信A用戶將消息發(fā)送到微信服務(wù)器,然后微信服務(wù)器判斷微信B用戶是否和微信服務(wù)器建立了長(zhǎng)連接,如果有直接通過(guò)微信B用戶和微信服務(wù)器建立的連接管道直接發(fā)送即可,這樣微信B用戶就能收到消息;如果微信B用戶此時(shí)沒(méi)有打開(kāi)微信App,那么微信服務(wù)器就將消息發(fā)送給蘋果服務(wù)器,蘋果服務(wù)器再講消息發(fā)送到某臺(tái)蘋果設(shè)備上。蘋果是怎么知道該發(fā)送給那臺(tái)設(shè)備呢?用戶A發(fā)送消息時(shí)需要將用戶B的UDID和微信App的Bundle ID 附帶在消息上一塊發(fā)送給B用戶,這些消息微信服務(wù)器又發(fā)送給蘋果服務(wù)器,蘋果服務(wù)器通過(guò)UDID就知道發(fā)送給那臺(tái)設(shè)備了,然后通過(guò)Bundle ID就知道是哪個(gè)App發(fā)送的了。蘋果根據(jù)UDID + Bundle ID 生成一個(gè)deviceToken, 這樣每條微信消息中都加上deviceToken蘋果服務(wù)器就能識(shí)別設(shè)備和App了。

圖形說(shuō)明
push1.png
push2.png
push3.png
實(shí)現(xiàn)步驟:
1. 創(chuàng)建真機(jī)調(diào)試證書并配置推送證書文件:apns_development.cer和描述文件

首先創(chuàng)建真機(jī)證書、AppIDs(要選擇Push Notifications), AppIDs創(chuàng)建完后可以看到狀態(tài)是Configurable,是黃色的圓點(diǎn),此時(shí)還不能使用推送通知,還要繼續(xù)配置一下,選擇Edit–>Push Notifications—> Create Certificate(創(chuàng)建推送通知證書),當(dāng)證書創(chuàng)建完成后,可以看到AppID中的狀態(tài)就變成了綠色的圓點(diǎn)(可用狀態(tài))

2. 請(qǐng)求蘋果服務(wù)器獲取deviceToken
import UserNotifications
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
       guard #available(iOS 10, *) else {
            // 請(qǐng)求授權(quán)
            let typeValue = UIUserNotificationType.alert.rawValue |
                UIUserNotificationType.badge.rawValue |
                UIUserNotificationType.sound.rawValue
            let type = UIUserNotificationType(rawValue: typeValue)
            let setting = UIUserNotificationSettings(types: type, categories: nil)
            UIApplication.shared.registerUserNotificationSettings(setting)
            
            // 發(fā)送請(qǐng)求
            UIApplication.shared.registerForRemoteNotifications()
            return
        }
        let typeValue = UNAuthorizationOptions.alert.rawValue |
            UNAuthorizationOptions.badge.rawValue |
            UNAuthorizationOptions.sound.rawValue
        UNUserNotificationCenter.current().requestAuthorization(options: UNAuthorizationOptions(rawValue: typeValue)) { (granted, error) in
            if granted { // 同意
                UIApplication.shared.registerForRemoteNotifications()
            } else { // 拒絕
                /// 彈出提示框
            }
        }
}
/// 當(dāng)請(qǐng)求到DeviceToken時(shí)調(diào)用
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    NSLog(deviceToken)
}
3. 發(fā)送deviceToken給App的服務(wù)器
//這里使用第三方阿里云推送SDK,所以在didRegisterForRemoteNotificationsWithDeviceToken中將deviceToken發(fā)送出去
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    NSLog(deviceToken)
    CloudPushSDK.registerDevice(deviceToken) { (result) in
       if result!.success {
          NSLog("Register deviceToken success.")
       } else {
          NSLog("Register deviceToken failed, error:\(result!.error!)")
       }
    }
}
4.監(jiān)聽(tīng)用戶點(diǎn)擊遠(yuǎn)程推送通知的行為
//鎖屏和從后臺(tái)進(jìn)入前臺(tái)會(huì)調(diào)用該方法
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
    NSLog(notification)
}
//在前臺(tái)調(diào)用下面該方法,該方法需要設(shè)置Background Modes --> Remote Notifications
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        let status = application.applicationState
        switch status {
        case .active:
            NSLog("在前臺(tái)收到推送")
            break
        case .inactive:
            NSLog("后臺(tái)->前臺(tái)")
            break
        case .background:
            NSLog("后臺(tái)")
            break
        }
        completionHandler(.newData)
}

上面那個(gè)代理方法都是用戶點(diǎn)擊通知以后才會(huì)調(diào)用,如果想一收到消息(用戶還沒(méi)點(diǎn)擊通知)就會(huì)調(diào)用該方法,需要有3個(gè)條件

  1. 設(shè)置Background Modes –> Remote Notifications
  2. 在代理方法中調(diào)用代碼塊completionHandler(UIBackgroundFetchResultNewData);
  3. App服務(wù)器發(fā)送數(shù)據(jù)時(shí)要增加一個(gè)”content-available”字段,值隨意寫
    滿足以上三個(gè)條件,當(dāng)接收到通知時(shí)立即會(huì)調(diào)用代理方法

備注:本文部分參考wxdtan的專欄雷潮文檔資料。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 點(diǎn)擊查看原文 Web SDK 開(kāi)發(fā)手冊(cè) SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 14,506評(píng)論 0 15
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,715評(píng)論 19 139
  • 推送通知和NSNotification是有區(qū)別的: NSNotification:是看不到的 推送通知:是可以看到...
    AA君主閱讀 2,398評(píng)論 0 7
  • 你要知道 我們都有這樣的時(shí)候 一席之間對(duì)全世界失去了興趣 最愛(ài)的音樂(lè)也變得燥耳 最愛(ài)的事情也懶得...
    羈安閱讀 222評(píng)論 1 4
  • “路途遙遠(yuǎn),一路安好?!?在這場(chǎng)人生中有太多的選擇需要你,不管你需不需要有時(shí)你不得不做出決定,看似我們有很多選擇,...
    維京vivian閱讀 372評(píng)論 0 1

友情鏈接更多精彩內(nèi)容