Swift-本地通知和远程通知

指推送通知跟NSNotification有区别:

1、NSNotification是系统内部发出通知,一般用于内部事件的监听,或者状态的改变等等,是不可见的
2、本地通知与远程通知是可见的,主要用于告知用户或者发送一些App的内容更新,推送一些相关的消息,让用户知道App内部发生了什么事情。

通知的注意点

1、App在前台运行的时候,通知不会展示出来
2、点击通知,默认会自动打开推送通知的App
3、不管App是否打开,通知都可以如期发出

1. 什么是本地推送通知

不需要联网就可以发出的通知

使用场景:

提醒用户完成一些任务,比如:定时提醒,生活备注,看电影等等

推送通知属性:
// 枚举值-发出通知的时间(有局限性)
@property(nonatomic) NSCalendarUnit repeatInterval;
// 自定义-发出通知的时间(可以自由设定时间)
@property(nonatomic,copy) NSCalendar *repeatCalendar;
// 区域-创建只需要创建一个中心点与半径就可以了
@property(nonatomic,copy) CLRegion *region
// 进入区域发出一个通知,设置yes,只会发出一个通知,设置NO就会每次进入这个区域都发送
@property(nonatomic,assign) BOOL regionTriggersOnce NO
// 设置通知的内容
@property(nonatomic,copy) NSString *alertBody;      
 // 决定alertAction是否生效
@property(nonatomic) BOOL hasAction;
// 设置滑块的文字
@property(nonatomic,copy) NSString *alertAction;    

// 设置点击通知的启动图片(一般设置App启动图片后,这里可以随便写)
@property(nonatomic,copy) NSString *alertLaunchImage;
// 设置alertTitle,就是通知内容上面的文字
@property(nonatomic,copy) NSString *alertTitle
 // 设置弹出的声音
@property(nonatomic,copy) NSString *soundName;
 // 设置App的消息条数
@property(nonatomic) NSInteger applicationIconBadgeNumber;
 // 设置通知一些额外数据
 @property(nonatomic,copy) NSDictionary *userInfo;
如何发出本地通知:
//发出一个电池电量为100的本地通知
let alertBody = "电池电量通知"
let localNotify = UILocalNotification()
localNotify.alertBody = alertBody
localNotify.soundName = UILocalNotificationDefaultSoundName
localNotify.userInfo = ["battery": 100]
UIApplication.shared.presentLocalNotificationNow(localNotify)

使用注意:
iOS7,不需要用户授权就可发出通知,而iOS8以后,必须用户授权才可以发出通知

//申请授权
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        guard #available(iOS 10, *) else {
            // 请求授权
            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)
            
            // 发送请求
            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 { // 拒绝
                /// 弹出提示框
            }
        }
}

监听通知,如果用户打开通知,可以让用户进入一些特定的界面

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

<1>从远程服务器推送给客户端的通知,需要连接网络
<2>远程推送服务,又称为APNs 苹果推送通知服务(Apple Push Notification services)
<3>模拟器无法调试远程推送

传统推送通知

传统推送通知是相对于APNs而言的,传统推送通知的原理是:当APP打开时和App的服务器建立一个长连接(需要网络),当需要通知的时候,App服务器通过长连接向对应的客户端发送数据,当客户端接收到数据时使用UILocalNotfication本地通知的方式来展示,这样就实现了传统推送通知。

传统推送通知必须要联网,如果关闭了App或者打开了App但是无法连接服务器了,这些情况都收不到通知了。

APNs

所有苹果设备在联网状态下都会与苹果服务器建立长连接,连接是双向的,苹果设备可以向苹果服务器发送请求,苹果服务器也可以向苹果设备发送请求。

苹果服务器常用的通知功能:

<1>时间校准
<2>系统升级
<3>查找我的iPhone
长连接的好处:更加及时

为什么需要远程推送通知:

解决获取传统数据的局限性,让数据实时更新

使用场景:

聊天功能(一般非即时聊天)、推送一下App的内部新功能、版本下载等

注:所有的苹果设备,在联网状态下,都会与苹果的服务器建立-长连接

远程通知的过程:

例如微信App:首先每个联网并打开微信的App都与微信服务器有一个长连接,当微信A用户向微信B用户发送一个消息时,微信A用户将消息发送到微信服务器,然后微信服务器判断微信B用户是否和微信服务器建立了长连接,如果有直接通过微信B用户和微信服务器建立的连接管道直接发送即可,这样微信B用户就能收到消息;如果微信B用户此时没有打开微信App,那么微信服务器就将消息发送给苹果服务器,苹果服务器再讲消息发送到某台苹果设备上。苹果是怎么知道该发送给那台设备呢?用户A发送消息时需要将用户B的UDID和微信App的Bundle ID 附带在消息上一块发送给B用户,这些消息微信服务器又发送给苹果服务器,苹果服务器通过UDID就知道发送给那台设备了,然后通过Bundle ID就知道是哪个App发送的了。苹果根据UDID + Bundle ID 生成一个deviceToken, 这样每条微信消息中都加上deviceToken苹果服务器就能识别设备和App了。

图形说明
push1.png
push2.png
push3.png
实现步骤:
1. 创建真机调试证书并配置推送证书文件:apns_development.cer和描述文件

首先创建真机证书、AppIDs(要选择Push Notifications), AppIDs创建完后可以看到状态是Configurable,是黄色的圆点,此时还不能使用推送通知,还要继续配置一下,选择Edit–>Push Notifications—> Create Certificate(创建推送通知证书),当证书创建完成后,可以看到AppID中的状态就变成了绿色的圆点(可用状态)

2. 请求苹果服务器获取deviceToken
import UserNotifications
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
       guard #available(iOS 10, *) else {
            // 请求授权
            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)
            
            // 发送请求
            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 { // 拒绝
                /// 弹出提示框
            }
        }
}
/// 当请求到DeviceToken时调用
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    NSLog(deviceToken)
}
3. 发送deviceToken给App的服务器
//这里使用第三方阿里云推送SDK,所以在didRegisterForRemoteNotificationsWithDeviceToken中将deviceToken发送出去
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.监听用户点击远程推送通知的行为
//锁屏和从后台进入前台会调用该方法
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
    NSLog(notification)
}
//在前台调用下面该方法,该方法需要设置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("在前台收到推送")
            break
        case .inactive:
            NSLog("后台->前台")
            break
        case .background:
            NSLog("后台")
            break
        }
        completionHandler(.newData)
}

上面那个代理方法都是用户点击通知以后才会调用,如果想一收到消息(用户还没点击通知)就会调用该方法,需要有3个条件

  1. 设置Background Modes –> Remote Notifications
  2. 在代理方法中调用代码块completionHandler(UIBackgroundFetchResultNewData);
  3. App服务器发送数据时要增加一个”content-available”字段,值随意写
    满足以上三个条件,当接收到通知时立即会调用代理方法

备注:本文部分参考wxdtan的专栏雷潮文档资料。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 13,652评论 0 15
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 推送通知和NSNotification是有区别的: NSNotification:是看不到的 推送通知:是可以看到...
    AA君主阅读 2,313评论 0 7
  • 你要知道 我们都有这样的时候 一席之间对全世界失去了兴趣 最爱的音乐也变得燥耳 最爱的事情也懒得...
    羁安阅读 180评论 1 4
  • “路途遥远,一路安好。” 在这场人生中有太多的选择需要你,不管你需不需要有时你不得不做出决定,看似我们有很多选择,...
    维京vivian阅读 278评论 0 1