系统推送的集成(五) —— 本地和远程通知编程指南之你的App的通知 - 调度和处理本地通知(三)

版本记录

版本号 时间
V1.0 2018.07.10

前言

我们做APP很多时候都需要推送功能,以直播为例,如果你关注的主播开播了,那么就需要向关注这个主播的人发送开播通知,提醒用户去看播,这个只是一个小的方面,具体应用根据公司的业务逻辑而定。前面已经花了很多篇幅介绍了极光推送,其实极光推送无非就是将我们客户端和服务端做的很多东西封装了一下,节省了我们很多处理逻辑和流程,这一篇开始,我们就利用系统的原生推送类结合工程实践说一下系统推送的集成,希望我的讲解能让大家很清楚的理解它。感兴趣的可以看上面几篇。
1. 系统推送的集成(一) —— 基本集成流程(一)
2. 系统推送的集成(二) —— 推送遇到的几个坑之BadDeviceToken问题(一)
3. 系统推送的集成(三) —— 本地和远程通知编程指南之你的App的通知 - 本地和远程通知概览(一)
4. 系统推送的集成(四) —— 本地和远程通知编程指南之你的App的通知 - 管理您的应用程序的通知支持(二)

Scheduling and Handling Local Notifications - 调度和处理本地通知

本地通知可让您在应用可能未运行时提醒用户。 您可以在应用程序在前台或后台运行时调度本地通知。 在调度通知后,系统负责在适当的时间向用户发送通知。 您的应用无需运行即可让系统发送通知。

如果您的应用未运行,或者它位于后台,系统会直接向用户显示本地通知。 系统可以通过警报面板或横幅,声音或通过标记应用程序的图标来警告用户。 如果您的应用提供了通知内容应用扩展程序,系统甚至可以使用您的自定义界面提醒用户。 如果您的应用在通知到达时位于前台,系统会为您的应用提供内部处理通知的机会。

注意:仅在iOS,watchOS和tvOS中支持本地通知。 在macOS中,应用程序在后台运行时不需要本地通知来标记其图标,播放声音或显示警报。 AppKit框架已经支持这些功能。


Configuring a Local Notification - 配置本地通知

配置本地通知的步骤如下:

在为通知创建内容时,请填写UNMutableNotificationContent对象的属性,以反映您希望与用户进行的交互类型。例如,如果要显示警报,请填写titlebody属性。系统使用您提供的信息来确定与用户交互的方式。处理已传递到应用程序的本地通知时,您还可以使用此对象中的数据。

创建通知内容后,创建一个触发器对象,定义何时传递通知。User Notifications框架提供基于时间和基于位置的触发器。使用所需条件配置触发器,并使用该对象和内容来创建UNNotificationRequest对象。

LIsting 3-1显示了如何创建和配置与闹钟相关的本地通知。使用UNCalendarNotificationTrigger会导致通知在特定日期或时间传递,在此示例中,下一次时钟到达早上7:00。

// Listing 3-1Creating and configuring a local notification
// OC

UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:@"Wake up!" arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:@"Rise and shine! It's morning time!"
        arguments:nil];
 
// Configure the trigger for a 7am wakeup.
NSDateComponents* date = [[NSDateComponents alloc] init];
date.hour = 7;
date.minute = 0;
UNCalendarNotificationTrigger* trigger = [UNCalendarNotificationTrigger
       triggerWithDateMatchingComponents:date repeats:NO];
 
// Create the request object.
UNNotificationRequest* request = [UNNotificationRequest
       requestWithIdentifier:@"MorningAlarm" content:content trigger:trigger];
// Swift
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "Wake up!", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "Rise and shine! It's morning time!",
                                                        arguments: nil)
 
// Configure the trigger for a 7am wakeup.
var dateInfo = DateComponents()
dateInfo.hour = 7
dateInfo.minute = 0
let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: false)
 
// Create the request object.
let request = UNNotificationRequest(identifier: "MorningAlarm", content: content, trigger: trigger)

UNNotificationRequest对象提供标识符为您提供了一种识别调度后的本地通知的方法。 您可以使用标识符稍后查找待处理的请求,并在到达之前取消它们。 有关调度和取消请求的详细信息,请参阅 Scheduling Local Notifications for Delivery

1. Assigning Custom Actions to a Local Notification - 将自定义操作分配给本地通知

要在界面中显示本地通知的自定义操作,请在配置期间将一个已注册的类别标识符分配给UNMutableNotificationContent对象的categoryIdentifier属性。 系统使用类别信息来确定要包含在通知界面中的操作按钮(如果有)。 在安排通知请求之前,必须为此属性分配值。

Listing 3-2显示了如何为本地通知指定类别标识符。 在此示例中,TIMER_EXPIRED字符串表示在启动时定义的类别,该类别包括两个自定义操作。 注册此类别的代码如Listing 2-3所示。

// Listing 3-2Defining a category of actions for a local notification
// OC

UNNotificationContent *content = [[UNNotificationContent alloc] init];
// Configure the content. . .
 
// Assign the category (and the associated actions).
content.categoryIdentifier = @"TIMER_EXPIRED";
 
// Create the request and schedule the notification.
// swift

let content = UNMutableNotificationContent()
// Configure the content. . .
 
// Assign the category (and the associated actions).
content.categoryIdentifier = "TIMER_EXPIRED"
 
// Create the request and schedule the notification.

有关如何使用类别注册自定义操作的信息,请参阅Configuring Categories and Actionable Notifications

2. Adding a Sound to the Notification Content - 向通知内容添加声音

如果您希望本地通知在传递时播放声音,请为UNMutableNotificationContent对象的sound属性指定值。 您可以使用UNNotificationSound对象指定声音,该对象允许您播放自定义声音或默认通知声音。 自定义声音必须位于用户设备本地才能播放。 将通知的声音文件存储在应用程序的主程序包中,或下载它们并将它们存储在应用程序容器目录的Library / Sounds子目录中。

要播放默认声音,请创建声音文件并将其指定给通知内容。 例如:

// OC
content.sound = [UNNotificationSound defaultSound];
// SWIFT
content.sound = UNNotificationSound.default()

指定自定义声音时,仅指定要播放的声音文件的文件名。 如果系统找到具有您提供的名称的合适声音文件,则在发送通知时播放该声音。 如果系统找不到合适的声音文件,它将播放默认声音。

// OC
content.sound = [UNNotificationSound soundNamed:@"MySound.aiff"];
//SWIFT
content.sound = UNNotificationSound(named: "MySound.aiff")

有关支持的声音文件格式的信息,请参阅UNNotificationSound Class Reference


Scheduling Local Notifications for Delivery - 调度本地通知送达

要调度送达的本地通知,请创建UNNotificationRequest对象并调用UNUserNotificationCenteraddNotificationRequest:withCompletionHandler:方法。 系统异步调度本地通知,在调度完成或发生错误时调用完成处理程序块。 Listing 3-3显示了如何调度本地通知以进行传递。 此示例中的代码完成了Listing 3-1中创建的通知的调度。

// Listing 3-3Scheduling a local notification for delivery
// OC

// Create the request object.
UNNotificationRequest* request = [UNNotificationRequest
       requestWithIdentifier:@"MorningAlarm" content:content trigger:trigger];
 
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
   if (error != nil) {
       NSLog(@"%@", error.localizedDescription);
   }
}];
// SWIFT

// Create the request object.
let request = UNNotificationRequest(identifier: "MorningAlarm", content: content, trigger: trigger)
 
// Schedule the request.
let center = UNUserNotificationCenter.current()
center.add(request) { (error : Error?) in
    if let theError = error {
        print(theError.localizedDescription)
    }
}

调度的本地通知保持活动状态,直到它们被系统取消调度或直到您明确取消它们为止。 除非通知的触发器配置为重复,否则系统会在发送后自动取消计划通知。 要在送达之前取消单个通知,或取消重复通知,请调用UNUserNotificationCenterremovePendingNotificationRequestsWithIdentifiers:方法。 被取消的通知必须具有分配给其UNNotificationRequest对象的identifier。要取消所有挂起的本地通知,无论它们是否具有请求标识符,请调用removeAllPendingNotificationRequests方法。


Responding to the Delivery of Notifications - 响应送达的通知

当您的应用未运行或处于后台时,系统会使用您指定的交互自动提供本地和远程通知。 如果用户选择某个操作,或选择其中一个标准交互,系统会通知您的应用用户的选择。 然后,您的代码可以使用该选择来执行其他任务。 如果您的应用在前台运行,则会将通知直接发送到您的应用。 然后,您可以决定是安静地处理通知还是提醒用户。

要响应通知的传递,您必须为单例UNUserNotificationCenter对象实现代理。 您的委托对象必须符合UNUserNotificationCenterDelegate协议,通知中心使用该协议向您的应用程序发送通知信息。 如果您的通知包含自定义操作,则需要委托。

重要:在应用程序或应用程序扩展完成启动之前,您必须将代理分配给单例UNUserNotificationCenter对象。 如果不这样做,可能会阻止您的应用正确处理通知。

有关如何实现代理对象的其他信息,请参阅UNUserNotificationCenterDelegate Protocol Reference

1. Handling Notifications When Your App Is in the Foreground - 处理您的应用程序在前台时的通知

如果在应用程序位于前台时收到通知,您可以静默该通知或告诉系统继续显示通知界面。默认情况下,在前台时系统会静默通知,并将通知的数据直接发送到您的应用。您可以使用通知数据直接更新应用程序界面。例如,如果到达新的体育比分,您只需在界面中更新该信息即可。

如果希望系统继续显示通知界面,请为UNUserNotificationCenter提供委托对象,并实现userNotificationCenter:willPresentNotification:withCompletionHandler:方法。您对此方法的实现仍应处理通知数据。完成后,使用您希望系统使用的传递选项(如果有)执行提供的完成处理程序块。如果未指定任何选项,系统会使通知静音。Listring 3-4显示了此方法的示例实现,它告诉系统播放声音。通知的有效负载payload标识要播放的声音。

// Listing 3-4Playing a sound while your app is in the foreground
// OC
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
        willPresentNotification:(UNNotification *)notification
        withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
   // Update the app interface directly.
 
    // Play a sound.
   completionHandler(UNNotificationPresentationOptionSound);
}
//SWIFT
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            willPresent notification: UNNotification,
                            withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    // Update the app interface directly.
    
    // Play a sound.
    completionHandler(UNNotificationPresentationOptions.sound)
}

当您的应用处于后台或未运行时,系统不会调用userNotificationCenter:willPresentNotification:withCompletionHandler:方法。 在这些情况下,系统根据通知本身中的信息警告用户。 您仍然可以使用UNUserNotificationCenter对象的getDeliveredNotificationsWithCompletionHandler:方法确定是否已发送通知。

2. Responding to the Selection of a Custom Action - 响应自定义操作的选择

当用户从通知界面中选择自定义操作时,系统会通知您的应用用户的选择。对自定义操作的响应打包在UNNotificationResponse对象中,并传递给应用程序的共享UNUserNotificationCenter对象的委托。要接收响应,您的委托对象必须实现userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:方法。您对该方法的实施必须能够处理您的应用或应用扩展程序支持的所有自定义操作。

如果收到回复后您的应用或应用扩展程序未运行,系统会在后台启动您的应用或应用扩展程序以处理响应。使用提供的后台时间更新数据结构和应用程序界面以反映用户的选择。请勿使用时间执行与自定义操作处理无关的任务。

Listing 3-5显示了具有多个类别和自定义操作的计时器应用程序的响应处理程序方法的实现。该实现使用actioncategoryIdentifier属性来确定适当的操作过程。

// Listing 3-5Handling a custom notification action
// OC

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
           didReceiveNotificationResponse:(UNNotificationResponse *)response
           withCompletionHandler:(void (^)(void))completionHandler {
    if ([response.notification.request.content.categoryIdentifier isEqualToString:@"TIMER_EXPIRED"]) {
        // Handle the actions for the expired timer.
        if ([response.actionIdentifier isEqualToString:@"SNOOZE_ACTION"])
        {
            // Invalidate the old timer and create a new one. . .
        }
        else if ([response.actionIdentifier isEqualToString:@"STOP_ACTION"])
        {
            // Invalidate the timer. . .
        }
 
    }
 
    // Else handle actions for other notification types. . .
}
// SWIFT
// func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {
    if response.notification.request.content.categoryIdentifier == "TIMER_EXPIRED" {
        // Handle the actions for the expired timer.
        if response.actionIdentifier == "SNOOZE_ACTION" {
            // Invalidate the old timer and create a new one. . .
        }
        else if response.actionIdentifier == "STOP_ACTION" {
            // Invalidate the timer. . .
        }
    }
    
    // Else handle actions for other notification types. . .
}

3. Handling the Standard System Actions - 处理标准系统操作

在系统的通知界面中,用户可以明确地关闭通知界面或启动您的应用,而不是选择您的一个自定义操作。关闭界面涉及点击适用按钮或直接关闭界面;忽略通知或轻弹通知横幅并不代表明确的移除。触发系统操作时,用户通知中心会将其报告给userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:代理方法。传递给该方法的响应对象包含以下操作标识符之一:

您可以像处理其他操作一样处理标准系统操作。Listing 3-6显示了userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:方法的模板用于检查这些特殊的actions

// Listing 3-6Handling the standard system actions
// OC
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
          didReceiveNotificationResponse:(UNNotificationResponse *)response
          withCompletionHandler:(void (^)(void))completionHandler {
   if ([response.actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier]) {
       // The user dismissed the notification without taking action.
   }
   else if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
       // The user launched the app.
   }
 
   // Else handle any custom actions. . .
}
// SWIFT

func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {
    if response.actionIdentifier == UNNotificationDismissActionIdentifier {
        // The user dismissed the notification without taking action
    }
    else if response.actionIdentifier == UNNotificationDefaultActionIdentifier {
        // The user launched the app
    }
    
    // Else handle any custom actions. . .
}

后记

本篇主要讲述了调度和处理本地通知,感兴趣的给个赞或者关注~~~~~

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

推荐阅读更多精彩内容