Swift - UserNotifications框架使用详解5(Actionable可交互通知)

十一、Actionable 可交互通知

从 iOS 8 起苹果就引入了可以交互的通知,其实现方式是把一组 action 放到一个 category 中,然后将这个 category 进行注册,最后在发送通知时将通知的 category 设置为要使用的 category 即可。到了 iOS10,苹果又对这些 action 做了统一。

1,效果图 

(1)下面是一个带有 action 交互的通知。设备接收到通知后默认的展示效果和普通的通知一样,点击通知同样也会打开应用。

(2)而当我们下拉或者使用 3D touch 展开通知后,就可以看到下方会出现对应的 action 按钮。

(3)这里我们添加了三个按钮,点击后的功能分别如下:

点击“点个赞”:自动打开应用,同时在程序界面上弹出用户操作信息。

点击“取消”:自动清除通知,且不会打开应用。(如果我们之后手动打开程序,界面上也会弹出用户操作信息。)

点击“评论”:界面下方会出现一个输入框。用户输入文字并提交后,会自动打开应用,同时在程序界面上弹出刚才输入的文字内容。

2,样例代码

(1)NotificationHandler.swift

为方便管理维护,这里我们将通知响应(action 响应)放在一个单独的文件中。并且将通知的 category 和 action 的标识符都定义成枚举。

import UIKit

import UserNotifications


//通知category标识符枚举

enum NotificationCategory: String {

    case news //新闻资讯通知category

}


//通知category的action标识符枚举

enum NotificationCategoryAction: String {

    case like

    case cancel

    case comment

}


//通知响应对象

class NotificationHandler: NSObject, UNUserNotificationCenterDelegate {

    //对通知进行响应(用户与通知进行交互时被调用)

    func userNotificationCenter(_ center: UNUserNotificationCenter,

                                didReceive response: UNNotificationResponse,

                                withCompletionHandler completionHandler:

        @escaping () -> Void) {

        //根据category标识符做相应的处理

        let categoryIdentifier = response.notification.request.content.categoryIdentifier

        if let category = NotificationCategory(rawValue: categoryIdentifier) {

            switch category {

            case .news:

                handleNews(response: response)

            }

        }

        completionHandler()

    }


    //处理新闻资讯通知的交互

    private func handleNews(response: UNNotificationResponse) {

        let message: String


        //判断点击是那个action

        if let actionType = NotificationCategoryAction(rawValue: response.actionIdentifier) {

            switch actionType {

            case .like: message = "你点击了“点个赞”按钮"

            case .cancel: message = "你点击了“取消”按钮"

            case .comment:

                message = "你输入的是:\((response as! UNTextInputNotificationResponse).userText)"

            }

        } else {

            //直接点击通知,或者点击删除这个通知会进入这个分支。

            message = ""

        }


        //弹出相关信息

        if !message.isEmpty {

            showAlert(message: message)

        }

    }


    //在根视图控制器上弹出普通消息提示框

    private func showAlert(message: String) {

        if let vc = UIApplication.shared.keyWindow?.rootViewController {

            let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)

            alert.addAction(UIAlertAction(title: "确定", style: .cancel))

            vc.present(alert, animated: true)

        }

    }

}

(2)AppDelegate.swift

这里除了申请通知权限外,还注册了一个 category,里面包括两个标准按钮 action,以及一个文本输入 action。

import UIKit

import UserNotifications


@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {


    var window: UIWindow?


    let notificationHandler = NotificationHandler()


    func application(_ application: UIApplication, didFinishLaunchingWithOptions

        launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        //请求通知权限

        UNUserNotificationCenter.current()

            .requestAuthorization(options: [.alert, .sound, .badge]) {

                (accepted, error) in

                if !accepted {

                    print("用户不允许消息通知。")

                }

        }


        //注册category

        registerNotificationCategory()

        UNUserNotificationCenter.current().delegate = notificationHandler


        return true

    }


    //注册一个category

    private func registerNotificationCategory() {

        let newsCategory: UNNotificationCategory = {

            //创建输入文本的action

            let inputAction = UNTextInputNotificationAction(

                identifier: NotificationCategoryAction.comment.rawValue,

                title: "评论",

                options: [.foreground],

                textInputButtonTitle: "发送",

                textInputPlaceholder: "在这里留下你想说的话...")


            //创建普通的按钮action

            let likeAction = UNNotificationAction(

                identifier: NotificationCategoryAction.like.rawValue,

                title: "点个赞",

                options: [.foreground])


            //创建普通的按钮action

            let cancelAction = UNNotificationAction(

                identifier: NotificationCategoryAction.cancel.rawValue,

                title: "取消",

                options: [.destructive])


            //创建category

            return UNNotificationCategory(identifier: NotificationCategory.news.rawValue,

                                          actions: [inputAction, likeAction, cancelAction],

                                          intentIdentifiers: [], options: [.customDismissAction])

        }()


        //把category添加到通知中心

        UNUserNotificationCenter.current().setNotificationCategories([newsCategory])

    }

}

(3)ViewController.swift

我们在程序界面打开后就创建通知(5 秒后推送)。特别注意的是要将通知的 categoryIdentifier 设置为需要的 category 标识符,这样系统就知道这个通知对应的是哪个 category。

import UIKit

import UserNotifications


class ViewController: UIViewController {


    override func viewDidLoad() {

        super.viewDidLoad()


        //设置推送内容

        let content = UNMutableNotificationContent()

        content.title = "hangge.com"

        content.body = "囤积iPhoneX的黄牛赔到怀疑人生?"

        //设置通知对应的category标识符

        content.categoryIdentifier = NotificationCategory.news.rawValue


        //设置通知触发器

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)


        //设置请求标识符

        let requestIdentifier = "com.hangge.testNotification"


        //设置一个通知请求

        let request = UNNotificationRequest(identifier: requestIdentifier,

                                            content: content, trigger: trigger)


        //将通知请求添加到发送中心

        UNUserNotificationCenter.current().add(request) { error in

            if error == nil {

                print("Time Interval Notification scheduled: \(requestIdentifier)")

            }

        }

    }


    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

    }

}

源码下载:

hangge_1845.zip

3,远程推送使用 category

远程推送也可以使用 category,只需要在 payload 报文中添加 category 字段,并指定预先定义的 category id 就可以了。

{

  "aps":{

    "alert":{

      "title":"hangge.com",

      "body":"囤积iPhoneX的黄牛赔到怀疑人生?"

    },

    "sound":"default",

    "badge":1,

    "category":"news"

  }

}

原文出自:www.hangge.com  转载请保留原文链接:https://www.hangge.com/blog/cache/detail_1847.html

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