本地通告和长距离公告

正文紧要描述了iOS的本地和远程布告的中央使用,以及某些不易注意的标题。

Note:作品有诸多身旁同学提供了声援,大批量引用或转发本文请宣示原文地址,多谢。

一:用户通报简介

用户通报是怎么

iOS中留存三种常见的风浪通报方式:NSNofiticationCenter、KVO Notification
和 User Notifications,其中 User
Notifications,就是本文将要研商的用户通报。

咱俩都知道 iOS 系统时常的有一些与 App
相关的布告栏音信,那几个音信往往伴随着提醒音以及 App
的桌面图标右上角的未读音信提示,这一个通告就是 iOS 的用户通报。

用户通报的分类

用户通报分为两类:本地布告和长距离文告,其中远程布告又称作推送文告。

两岸最器重的界别是:本地布告是由 App
发送到当前设备上,不须求网络辅助;而远程文告是由 App
的服务器发送到苹果的 APNs 服务器,并由 APNs 服务器转载到相应设施(由 App
服务器指定接收公告的装备)。

两边最要害的共同点是:本地通告和长途通告对用户的表现格局是一模一样的,两者均可以行使文告栏消息、App
桌面图标右上角角标和提示音的艺术布告用户。

用户通报有何样用场

即时得力的(无论是在前台仍旧后台)向用户发送音信(聊天音信、消息、待办事项、天气变化等)是用户通报最大的优势。

其余,有效制造的拔取用户通报,可以让我们的 App 有更好的经验,如:

  • 当待办事项将要过期时方可登时指示用户;
  • 当用户执行下载大文件职责时进入后台,当下载完结后可以通报用户;
  • 当用户全世界旅行时,可以根据用户的地理地点推送天气变化等信息;
  • 当用户订阅的某杂志或音信主旨有创新时,通告用户;
  • ……

正文后续内容将以利用开发者的角度对用户通报进行深刻的追究,本文钻探内容针对iOS7/8/9,有关
iOS10 系统的用户通报会另做讲解。

此地可下载
本文demo
。其它,本文中的远程公告使用了
Simplepush.php
,内部代码很不难,可利用该脚本自定义远程布告的情节,当然可以应用
本文demo
里我修改过的脚本文件,提出花几分钟查看以下 Simplepush.php
的用法。其余,demo
不提供证件,如有远程通告要求,请自行报名证书,否则不能正常使用
Simplepush。

本文主要参考了苹果官方的 Local and Remote Notification Programming
Guide

以及本文用到的接口的法定文档。

二:本地公告的施用

开启本地公告效率

  • 对于 iOS7,假使用户并未在系统设置里关闭该 App
    的打招呼作用,那么开发者无需做其它操作即可使用当地公告作用。

  • 对于 iOS8
    及其后的体系,若必要选用当地公告功效,则必要登记公告类型。
    通报类型有多样:角标(UIUserNotificationTypeBadge)、提醒音(UIUserNotificationTypeSound)、提醒音信(UIUserNotificationTypeAlert)和无任何布告(UIUserNotificationTypeNone)。

    你可以挂号上诉八种通告类型的轻易组合,但结尾可用的公告方式需要按照用户对此
    App 公告的设置规定。比如:App
    内部注册了角标、提醒音和提示音讯,然而用户关闭了音响布告,那么收到本地文告时是不会有提醒音的。
    对于 iOS8 及然后的连串,注册本地布告的代码示例如下:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // 只有 iOS8 and later 才需要
        if ([[UIApplication sharedApplication]  respondsToSelector:@selector(registerForRemoteNotifications)]) {
            // 这里 types 可以自定义,如果 types 为 0,那么所有的用户通知均会静默的接收,系统不会给用户任何提示(当然,App 可以自己处理并给出提示)
            UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert);
            // 这里 categories 可暂不深入,本文后面会详细讲解。
            UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
            // 当应用安装后第一次调用该方法时,系统会弹窗提示用户是否允许接收通知
            [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
        }
    
        // Your own other codes.
        return YES;
    }
    

当系统弹窗提醒用户是还是不是同意收取通告后,用户可能会拒绝;大家能够在
AppDelegate 的 application:didRegisterUserNotificationSettings:
方法中用来查阅注册成功的关照类型,大家得以在获得注册结果后做自定义操作(比如失利时弹个窗提醒用户眼前不能利用用户通报)。

苹果推荐在随后发送的当地文告时,要幸免使用没有登记成功的公告类型(并不是挟持需要)。

- (void)application: (UIApplication*)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    if (notificationSettings.types & UIUserNotificationTypeBadge) {
        NSLog(@"Badge Nofitication type is allowed");
    }
    if (notificationSettings.types & UIUserNotificationTypeAlert) {
        NSLog(@"Alert Notfication type is allowed");
    }
    if (notificationSettings.types & UIUserNotificationTypeSound) {
        NSLog(@"Sound Notfication type is allowed");
    }
}

发送本地布告

出殡一个本土公告紧要有如下步骤:

  1. 率先要循规蹈矩上述 “开启本地公告作用” 步骤注册通告类型;

  2. 创设一个 UILocalNotification 对象;

  3. 设置 UILocalNotification 对象的 fireDate
    属性,该属性表示什么日子点发送那条地点通告;同时可以安装 timeZone
    属性表示时区,设置 timeZone 后,当用户当先时区时,fireDate
    会按照时区被调动(类似于钟表调整);其它,可以行使 repeatInterval 和
    repeatCalendar 来安装周期性的文告。

  4. 设置布告的提醒音信:

    • 设置 alertTitle 作为通告的概要,设置 alertBody
      作为公告的实际新闻;注意那里强烈指出使用本地化的字符串,即
      NSLocalizedString(@"This is alert body", nil);
      注意 alertTitle 属性只适用于 iOS8.2 及之后的种类
    • 安装 applicationIconBadgeNumber 用于展示 App
      桌面图标的右上角角标。
    • 安装 soundName, 大家一般安装为
      UILocalNotificationDefaultSoundName;使用自定义 sound
      在末端会尤其讲解。
    • 在设置提示格局的值时,对于 iOS8
      及然后的系统,可以检查下当前唤起方式是还是不是业已登记成功(可以用
      [[UIApplication sharedApplication] currentUserNotificationSettings]
      获取注册成功的打招呼类型)。
  5. 可以选拔安装 userInfo 属性,该属性一般可以存放业务有关的消息(如 ID
    等),这样收到布告后方可一本万利处监护人情有关逻辑;

  6. 将地点创立的 UILocalnotification 放入公告队列中:使用办法
    scheduleLocalNotification: 会按照 UILocalnotification 中的
    fireDate 举行通报的出殡,而选择 presentLocalNotificationNow:
    会马上发送该地方布告。

下边给出一段示例代码:

- (void)scheduleLocalNotification {
    NSDate *itemDate = [NSDate date];

    UILocalNotification *localNotif = [[UILocalNotification alloc] init];
    if (localNotif == nil)
        return;
    localNotif.fireDate = [itemDate dateByAddingTimeInterval:10];
    localNotif.timeZone = [NSTimeZone defaultTimeZone];

    localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"%@ after %i seconds scheduled.", nil), @"本地通知", 10];

    localNotif.alertTitle = NSLocalizedString(@"Local Notification Title", nil);

    localNotif.soundName = UILocalNotificationDefaultSoundName;
    localNotif.applicationIconBadgeNumber = 1;

    NSDictionary *infoDict = [NSDictionary dictionaryWithObject:@"ID:10" forKey:@"LocalNotification"];
    localNotif.userInfo = infoDict;

    [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}

拍卖收到的本地文告

那里分两种处境研究哪边处理地点通告:

使用处于前台

选择处于前台时,本地布告到达时,不会有提示音、公告栏横幅提醒,可是 App
桌面图标的右上角角标是有数值显示的,所以即便在前台,大家也应该对角标数量做拍卖
此刻,大家得以在 application:didReceiveLocalNotification:
方法中拿走到地点公告,示例代码如下:

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    NSString *itemName = [notification.userInfo objectForKey:@"LocalNotification"];
    [self.windowRootController displayNotification:[NSString stringWithFormat:@"%@ receive from didReceiveLocalNotificaition", itemName]];
    // 这里将角标数量减一,注意系统不会帮助我们处理角标数量
    application.applicationIconBadgeNumber -= 1;
}

应用处于后台

当使用处于后台时,本地布告到达时,会按照当地文告设置的打招呼类型以及用户安装的打招呼类型进行提醒,例如锁屏界面布告、通知栏公告、声音、角标。

此时一旦滑动锁屏界面布告或点击通告栏公告,则会切换应用到前台,我们可以使用与行使处于前台时一样的得到公告的措施。

只是只要大家点击 App
桌面图标,则不能取得到用户通报,此时布告栏新闻照旧会设有。其余,角标也不会变卦,即使指望修改角标,则需要App 进入前台后将其修改。

运用尚未运行

设若运用尚未运行,当本地布告到达时,会基于当地通告设置的关照类型以及用户安装的文告类型举办提醒,例如锁屏界面公告、文告栏文告、声音、角标。此时倘诺滑动锁屏界面布告或点击布告栏通告,则会打开应用,但此时大家获取布告的章程与眼前有所分化,通过application:didReceiveLocalNotification:
是不能取得通告的。 这种状态大家需求经过
application:didFinishLaunchingWithOptions: 中的 LaunchOptions
获取通告,示例代码如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    if (localNotif) {
        NSString *itemName = [localNotif.userInfo objectForKey:@"LocalNotification"];
        [self.windowRootController displayNotification:[NSString stringWithFormat:@"%@ receive from didFinishLaunch", itemName]];  // custom method
        [UIApplication sharedApplication].applicationIconBadgeNumber = localNotif.applicationIconBadgeNumber-1;
    }

    // Your own other codes.
    return YES;
}

同等的,不过一旦我们点击 App
桌面图标,则无从获取到用户通报,此时布告栏新闻依然会存在。别的,角标也不会变动,如果期望修改角标,则要求App 进入前台后将其修改。

地理地方相关的本地文告

在 iOS8
及未来系统中,大家得以定义一个与地理地方有关的地头通告,那样当大家跨过设定的地理区域时,系统会发送本地文告。

注册地点相关的地面通知

  1. 亟待成立一个 CLLocationManager 对象,并为其设置一个 delegate;

  2. 恳请用户同意行使固定服务:调用 CLLocationManager 的
    requestWhenInUseAuthorization,注意工程的 plist 中需求配备
    NSLocationWhenInUseUsageDescription
    选项,否则一定服务无法正常启用;示例代码如下:

    - (void)registerLocationBasedNotification {
        CLLocationManager *locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        // 申请定位权限
        [locationManager requestWhenInUseAuthorization];
    }
    
  3. 因而 CLLocationManagerDelegate
    回调检查用户是还是不是同意选拔固定服务,假如允许了劳动,那么可以发送一个岗位相关的地面布告。

    - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
        // 因为上面我们是使用了 requestWhenInUseAuthorization,所以这里检查的是 kCLAuthorizationStatusAuthorizedWhenInUse
        if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
        [self scheduleLocalBasedNotification];
        }
    }
    
  4. 始建一个地点相关的当地公告,并将其交由系统处理。

    - (void)scheduleLocalBasedNotification {
        UILocalNotification *locationNotification = [[UILocalNotification alloc] init];
        locationNotification.alertBody = @"到达xxx";
        locationNotification.regionTriggersOnce = NO; // 表示每次跨越指定区域就会发送通知
        locationNotification.region = [[CLCircularRegion alloc] initWithCenter:LOC_COORDINATE radius:LOC_RADIUS identifier:LOC_IDENTIFIER];
    
        [[UIApplication sharedApplication] scheduleLocalNotification:locNotification];
    }
    

拍卖地方相关的地头文告

与地方讲过的 “处理收到的地点文告” 相比较,那里可以在布告里获得到
region,然后可以做自定义操作,其他具备操作均与 “处理收到的本地通告”
一致。

注意要是用户没有允许利用一定权限,则无从吸收地方相关的本地通告。

三:远程文告的施用

APNs 简介

APNs 是苹果提供的远程通知的服务器,当 App 处于后台或者尚未运行时,假使App 的服务器(之后大家称为
Provider)要求发送文告音信给客户端,则需求重视 APNs 服务器。

接纳 APNs 服务时,远程通告的路由路径为: Provider –> 苹果的 APNs
服务器 –> 手机设备 –> App。在那个途径中,Provider 与 APNs
服务器之间有一个 TLS 连接,Provider 通过这些延续将远程公告推送到苹果的
APNs 服务器;手机配备与 APNs 服务器之间也会有一个 TLS
连接,所有发往手机设备的 APNs 远程通告都是采用那么些TLS连接,然后由装备区分远程公告所属的
App,进而文告给用户某应用有长途公告。

下边简单介绍下这一个流程:

设备 与 APNs

设施与 APNs 建立连接的历程如图:

Device-APNs.png

要求明确的要点:

  1. 此三番五次由系统建立并有限支撑,无需开发人士管理;
  2. 上图中的证书是苹果设备本身的证书,与开发者账号中申请的注解无关;
  3. 每个设备与 APNs 服务器只需维持一条连接。

Provider 与 APNs

Provider 与 APNs 建立连接的历程如图:

Provider-APNs.png

要求精通的要义:

  1. 此三番五次由 App 的 bundle ID 唯一确定;
  2. 上图中 Provider certificate 需要通过开发者账号申请变更,其中包涵 App
    的 bundle ID。

APNs 工作的流水线

Provider-App.png

  1. 率先客户端需要向 APNs 服务器注册当前 App,APNs
    会再次回到一个Token(注意那么些进程需求 App
    有合法的表明,有关注明那里不做详细描述);注意分化采纳在一如既往设备上收获的
    Token 差异,同一应用在分歧装备上取得的 Token也不比,所以 Token
    是跟设备与 App 唯一绑定的;

  2. App 得到 Token 后须要将其发送给 Provider;

  3. Provider 发送推送通告时,指定 Token 和文告内容,并发送给 APNs
    服务器;

  4. APNs 服务器会将布告发送给 Token 对应的装备上;

  5. 配备收到布告后,依据 APNs 发过来的公告中含有的 bundleID
    新闻分别是哪些App的长距离通告(那里应该是按照 Token 来获得 bundleID)。

Feedback 机制

Feedback 是 APNs
服务器提供的用来减弱服务器压力以及优化互联网的劳务,基本的工作流程如下图:

APNs-Feedback.png

  1. Provider 发送一个长距离通告给 APNs 服务器,APNs
    服务器会检测目标设备是不是在线,假如不在线,那么 APNs
    服务器会暂存该新闻;

  2. 当目的装置上线后,APNs
    会发送暂存的音信给目标设备(按照苹果官方说法暂存音信只会暂存最终一条信息,从前的新闻会被放任);

  3. 设若目标设备很久都尚未上线,那么 APNs 新闻会把该设备进入 feedback
    名单。Provider 可以定期去 APNs 拉新 feedback 名单;

  4. 当 Provider 再度给后面的设施发送远程通告时,必要检查一下 feedback
    名单,假若设备在这几个名单,则不再发送给 APNs 了;

  5. 当设备再一次上线后,Provider 可以再将此设施移除 feedback 名单,当
    Provider 更新 feedback list
    后,就可以再一次给该装置发送远程文告了。当然,feedback list
    的立异可能会有周期,假使要求马上有效的换代 feedback list,那么需要App 打开后,及时通告 Provider;

  6. 那种体制的益处就是预防发送多余无用的长途文告音信,一方面可以减缓
    APNs 服务器的压力,另一方面也可以收缩互联网流量;

打开远程文告成效

注册布告类型

  • 对于 iOS7,无需此步骤;
  • 对此 iOS8
    及今后的系统,若必要选择远程文告功效,则须求登记文告类型。步骤与
    “本地通告的选取” 中 “开启本地通知成效” 是完全相同的,此处不再另行。

挂号远程文告

主题流程为:

  1. 挂号文告类型,上一小节已经做了介绍;
  2. 使用 registerForRemoteNotifications 注册远程通告(对于 iOS7 使用
    registerForRemoteNotificationTypes:);
  3. 使用 application:didRegisterForRemoteNotificationsWithDeviceToken:
    接收 APNs 返回的 Token,使用
    application:didFailToRegisterForRemoteNotificationsWithError:
    处理登记错误;
  4. 比方上一步骤中登记成功了,那么将收获的 Token 发送给 Provider。

注意:

  1. 现阶段总的来说,对于 iOS9,每一回重新安装应用后获取的 Token
    是分化的,而且每趟重装系统也会变动,所以
    每一遍应用启动时都亟待按上边的手续注册三次

  2. 永不将此前的 Token 缓存,当须要将 Token 传送到 Provider
    时,一定要选择 registerForRemoteNotifications
    获取,并应用回调处理登记结果;当使用注册过文告,而且 Token
    没有改动时,系统会立刻回到结果,不会去 APNs 请求。那里预计系统帮忙将
    Token
    缓存下来,且与使用的情形进行了涉嫌,假设采用当前事态并未变动,那么会即刻将系统存下的
    Token 重回。为了证实那点,可以将互连网关闭举办测试,假设 App
    没有卸载,也是足以博得到 Token 的;

  3. 自然要有打开了 Push 成效的阐明,才能正常使用远程推送。

注册远程公告的演示代码如下:

- (void)registerRemoteNotifications {
    // 区分是否是 iOS8 or later
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)]) {
        // 这里 types 可以自定义,如果 types 为 0,那么所有的用户通知均会静默的接收,系统不会给用户任何提示(当然,App 可以自己处理并给出提示)
        UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert);
        // 这里 categories 可暂不深入,本文后面会详细讲解。
        UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        // 当应用安装后第一次调用该方法时,系统会弹窗提示用户是否允许接收通知
        [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
    } else {
        UIRemoteNotificationType types = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
    }
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(nonnull UIUserNotificationSettings *)notificationSettings {
    // Register for remote notifications.
    [[UIApplication sharedApplication] registerForRemoteNotifications];
}

// Handle register result.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    //获得 device token,这一步处理为字符串的操作很重要
    NSString *token = [[[deviceToken description]
                        stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]
                        stringByReplacingOccurrencesOfString:@" "
                        withString:@""];
    NSLog(@"DeviceToken string, %@", token);
    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
    // 将 token 发送给 Provider
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Error in registration for apns service. Error: %@", error);
}

出殡远程布告

长距离布告的始末

Provider 发送给 APNs 服务器的情节格式如下:

{
   // aps key 是必须要有的
   "aps" : {
      "alert" : {
         "title" : "通知的概要,对 8.2 以前的系统本选项无效"
         "body" : "通知的具体内容",
         "loc-key" : "GAME_PLAY_REQUEST_FORMAT",
         "loc-args" : [ "Jenna", "Frank"]
      },
      "badge" : 3, // 角标数值
      "sound" : “chime.aiff" // 可以自定义提示音
   },

   "userName" : "username", // aps key 之外可以有自定义内容,需要符合 json 格式
   "message" : ["hello", "world", "programmer"]
}

上面只是简短介绍了广阔的情节,如需求进一步深度定制推送布告,提议查看:
苹果官方payload文档

远程通告的本地化处理

有二种艺术:

  • 在 Provider 端进行本地化
    App 可以将近日选择的言语发送给 Provider,Provider
    在发送远程文告前,检查当前配备选择的言语,并做好本地化后发送给 APNs
    服务器。App 发送当前利用的言语给 Provider 的演示代码:

    NSString *preferredLang = [[NSLocale preferredLanguages] objectAtIndex:0];
    const char *langStr = [preferredLang UTF8String];
    [self sendProviderCurrentLanguage:langStr]; // custom method
    

    诚如的话,将方今系统语言音信发送给 Provider 时,也会将 Token
    一起发送,那样 Provider
    才可以在殡葬远程公告时按照分化目标设备开展本地化处理。
    除此以外,当使用启动后,用户可能会修改系统语言,那时,App 必要监听
    NSCurrentLocaleDidChangeNotification
    通告,并在处理通报的法门中另行向 Provider 发送当前使用的言语。

  • 在客户端本地化
    那种格局下,Provider 在发送远程通告时,必要安装 Payload -> alert
    中的本地化相关属性,如下:

    {
        // aps key 是必须要有的
        "aps" : {
            "alert" : {
                      "title" : "通知的概要,对 8.2 以前的系统本选项无效",
                      "loc-key" : "Remote Notification",
                      "loc-args" : [ "hello", "world"]
            },
            "badge" : 3, // 角标数值
            "sound" : “chime.aiff" // 可以自定义提示音
        }
    }
    

地点 loc-key 以及 loc-args 就是本地化相关的质量,用于地点化 alert 中的
body。
当 App 收到此音讯时,会根据系统当下的语言设置去相应的本地化文件中寻觅与
loc-key 对应的 value,倘若 loc-key 对应的 value
是一个格式化的字符串,那么可以用 loc-args 传递参数。

比方本地化文件中: “Remote Notification” = “大家程序员寻常钟爱:%@ %@”
,那么提醒新闻就是: “大家程序员钟爱:hello world”;

除此以外在本地化文件中大家也可以用 %n$@ 代替 %@ 用来代表使用 loc-args
的第多少个参数。例如:”Remote Notification” = “大家程序员平常钟爱:%2$@
%1$@”,那么提醒音讯是:”我们程序员钟爱:world hello”。

相同的,title-loc-key 和 title-loc-args 是对 alert 中的 title
做本地化的。

拍卖收到的中远距离文告

此间分二种情景研究怎么着处理远程通告:

选拔处于前台

动用处于前台时,本地公告到达时,不会有提醒音、公告栏横幅提醒。不过 App
桌面图标的右上角角标是有数值突显的,所以就是在前台,大家也相应对角标数量做拍卖;
那时候,大家得以在
application:didReceiveRemoteNotification:fetchCompletionHandler:
方法中赢获得长途文告,示例代码如下:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler {
    NSData *infoData = [NSJSONSerialization dataWithJSONObject:userInfo options:0 error:nil];
    NSString *info = [[NSString alloc] initWithData:infoData encoding:NSUTF8StringEncoding];
    [self.windowRootController displayNotification:[NSString stringWithFormat:@"From didReceiveRemoteNotification: %@", info]];
    // 这里将角标数量减一,注意系统不会帮助我们处理角标数量
    application.applicationIconBadgeNumber = notification.applicationIconBadgeNumber - 1;
}

利用处于后台

当使用处于后台时,远程布告到达时,会依据登记布告是设置的关照类型以及用户设置的布告类型进行提示,例如锁屏界面文告、布告栏公告、声音、角标。

这儿只要滑动锁屏界面通知或点击通告栏文告,则会切换应用到前台,我们可以动用与行使处于前台时一样的获得布告的主意。

可是只要大家点击 App
桌面图标,则无从取得到用户通报,此时通知栏音信如故会存在。其余,角标也不会变卦,固然指望修改角标,则须要App 进入前台后将其修改。

拔取尚未运行

此间有三种处理方式:

  • 与本地文告的处理方式相同,在
    application:didFinishLaunchingWithOptions: 的 LaunchOptions
    中赢得公告,然则其中代码会略有分化,示例如下:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        NSDictionary *remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        if (remoteNotif) {
            NSData *infoData = [NSJSONSerialization dataWithJSONObject:remoteNotif options:0 error:nil];
            NSString *info = [[NSString alloc] initWithData:infoData encoding:NSUTF8StringEncoding];
            [self.windowRootController displayNotification:[NSString stringWithFormat:@"From didFinishLaunch: %@", info]];
            [UIApplication sharedApplication].applicationIconBadgeNumber -= 1;
        }
        // Your own other codes.
        return YES;
    }
    
  • 与应用处于前后台时处理方式相同,使用application:didReceiveRemoteNotification:fetchCompletionHandler:
    方法,示例代码见 “应用处于前台”
    时的处理。对于远程文告,推荐使用此种形式处理。

    除此以外,对于远程公告,如若大家点击 App
    桌面图标,则不能获获得用户通报,此时通告栏音讯仍旧会设有。其它,角标也不会转变,若是愿意修改角标,则需求App 进入前台后将其修改。

长途公告-静默推送

沉默寡言推送是指利用在前台或后台状态下,收到远程公告时,没有弹窗或横幅提示,就算远在后台也得以拍卖远程公告。具体行使流程如下:

  1. 开拓应用工程 Target 的 Capacities,将 Background Modes
    选项打开,并且勾选 Remote Notifications;

  2. 在 Provider 发送远程公告时,须要将远程公告 Payload 中的 aps 内的
    content-available 设置为 1,如下:

     aps {  
         content-available: 1
         alert: {...}
     }
    
  3. 选择要求完成
    application:didReceiveRemoteNotification:fetchCompletionHandler:
    方法接收静默推送。

有几点须要专注:

  1. 行使静默推送时,alert 字段不应当其他音信,但足以设置 aps
    内的自定义字段;
  2. sound 和 badge 字段可以安装,但极致不安装,否则会有提醒音;
  3. 沉吟不语推送只有当使用处于前台或后台时才能处理,当使用尚未启动时是收不到静默推送的;
  4. 拍卖静默推送时,无法做耗时操作,因为系统只为那种处理作为分配少量时间,如下载文件之类的操作请使用后台下载服务。

可操作文告

率先须要留意的是,可操作通告只适用于 iOS8 及事后的系统。

可操作布告其实并不是一种新的文告格局,它只是在那地点公告和远程通告的底子上加了一些可操作的行事而已。为了直观表明如何是可操作文告,可以参照下图:

Actionable-Notification.png

可操作通告为用户提供了在文告提醒中有益执行操作的点子,在利用横幅提醒通知新闻时,最多可以有几个操作,在运用弹窗提醒文告信息是,最多能够有三个操作。上边讲解如何运用:

四:定义可操作布告的一言一动

主题选取办法:

  1. 创办一个 UIMutableUserNotificationAction
    对象,并按必要安顿该对象的性质,示例代码:

    UIMutableUserNotificationAction *acceptAction = [[UIMutableUserNotificationAction alloc] init];
    // 为该操作设置一个 id
    acceptAction.identifier = @"accept";
    // 设置该操作对应的 button 显示的字符串
    acceptAction.title = @"Accept";
    // 指定是否需要应用处于运行状态
    acceptAction.activationMode = UIUserNotificationActivationModeBackground;
    // 表示该操作是否有害,若设置为 YES,则对应的button会有高亮
    acceptAction.destructive = NO;
    // 当锁屏时收到可操作通知,该属性表示是否必须解锁才能执行该操作
    acceptAction.authenticationRequired = YES;
    
  2. 制造一个 UIMutableUserNotificationCategory
    对象,并将自定义的操作通过 setActions: 的艺术设置给 category
    对象。代码如下:

    // 这里为了测试,又新建了两个 action,declineAction 和 maybeAction ,代码可见 demo
    UIMutableUserNotificationCategory *inviteCategory = [[UIMutableUserNotificationCategory alloc] init];
    // 设置一个 ID,用于本地通知或远程通知时指定该通知可执行的操作group
    inviteCategory.identifier = @"Action";
    // 为弹窗模式设置 actions
    [inviteCategory setActions:@[acceptAction, maybeAction, declineAction] forContext:UIUserNotificationActionContextDefault];
    // 为横幅模式设置 actions
    [inviteCategory setActions:@[acceptAction, declineAction] forContext:UIUserNotificationActionContextMinimal];
    
  3. 挂号布告类型以及可操作的actions

    就像于地面公告和长途文告,调用 registerUserNotificationSettings:
    注册通告,只是那里的 setting 参与了大家地方定义的 category。

    NSSet *categories = [NSSet setWithObjects:inviteCategory, nil];
    // 这里 types 可以自定义,如果 types 为 0,那么所有的用户通知均会静默的接收,系统不会给用户任何提示(当然,App 可以自己处理并给出提示)
    UIUserNotificationType types = (UIUserNotificationType) (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert);
    // 这里 categories 可暂不深入,本文后面会详细讲解。
    UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:categories];
    // 当应用安装后第一次调用该方法时,系统会弹窗提示用户是否允许接收通知
    [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
    

假诺将可实施文告用于远程公告,那么要求坚守长途通知的登记格局得到token,可参看远程布告的注册。

出殡可操作文告

事先说过,可操作公告只是在本土文告和长距离文告的根底上加了自定义的操作,所以发送可操作文告就是殡葬本地通告或远程通告。但是,如若希望我们自定义的
action 有效,在发送本地公告或远程公告时要求进行部分变更:

  • 本地文告的可操作公告
    为 UILocalNotification 对象设置我们自定义的 category。如下:

    UILocalNotification *notification = [[UILocalNotification alloc] init];
    // Other configurations
    notification.category = @"Action";
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
    
  • 长途公告的可操作布告
    在中远距离通告的 Payload 中装置我们自定义的 category,如下:

    {
        "aps" :  {
            "alert" : "You’re invited!",
            "category" : "Action"
        }
    }
    

拍卖可操作通告

处理可操作文告与拍卖地点文告和长距离布告一致,唯一的分裂点就是当用户执行了某个操作后,应用可以在后台运行application:handleActionWithIdentifier:forRemoteNotification:completionHandler:
处理通报(例如后台更新数据等操作),我们得以在这么些回调里很快的施行操作:

- (void)application:(UIApplication *) application
              handleActionWithIdentifier: (NSString *) identifier
          // either forLocalNotification: (NSDictionary *) notification or
                   forRemoteNotification: (NSDictionary *) notification
                       completionHandler: (void (^)()) completionHandler {

    if ([identifier isEqualToString: @"accept"]) {
        [self handleAcceptActionWithNotification:notification];
    }

    // 执行自定义代码完成后必须调用
    completionHandler();
}

对于地点布告大家可以应用
application:handleActionWithIdentifier:forLocalNotification:completionHandler:

可操作布告到底有怎样便宜?

此地举个例证表明:
即使A向B发出了一个列席发表会约请,并且 App
是以长途通告的法门接受到该消息,那么当不使用可操作文告的时候,大家需要做的事务根本概括:

  1. 用户须求开拓应用;
  2. App 查看远程公告的情节是一个特约,那么 App
    应该弹窗提醒用户是或不是接受该特邀;
  3. 用户选用后,App 通过 Http(也可以动用别的通信协议)
    将结果回到给服务器;
  4. 特邀文告处理达成。

那么,如若大家拔取可操作通告,可以很不难的成功那件工作:

  1. 用户挑选接受或拒绝邀约(用户无需打开 App);

  2. App 通过可操作布告的回调处理用户操作结果,将结果发送给服务器;

  3. 约请布告处理达成。

    可以看到,不论是从用户角度如故开发者角度,可操作通告都大幅度的便宜了处理具有可操作动作的那类公告。

五:总结

必发bifa88手机客服端,到那边曾经讲解完结了用户通报的内容,小说包罗了苹果给出的用户通报的中坚具备用法,要是想要确认文档是还是不是有误可自动参考
Local and Remote Notification Programming
Guide

,假若本文中情节有误,欢迎提出与座谈。

相关文章