Swift - UserNotifications框架使用详解5(Actionable可交互通知)
十一、Actionable 可交互通知
从 iOS 8 起苹果就引入了可以交互的通知,其实现方式是把一组 action 放到一个 category 中,然后将这个 category 进行注册,最后在发送通知时将通知的 category 设置为要使用的 category 即可。到了 iOS10,苹果又对这些 action 做了统一。
1,效果图
(1)下面是一个带有 action 交互的通知。设备接收到通知后默认的展示效果和普通的通知一样,点击通知同样也会打开应用。
 
  
(2)而当我们下拉或者使用 3D touch 展开通知后,就可以看到下方会出现对应的 action 按钮。
 
  
(3)这里我们添加了三个按钮,点击后的功能分别如下:
- 点击“点个赞”:自动打开应用,同时在程序界面上弹出用户操作信息。
- 点击“取消”:自动清除通知,且不会打开应用。(如果我们之后手动打开程序,界面上也会弹出用户操作信息。)
-   点击“评论”:界面下方会出现一个输入框。用户输入文字并提交后,会自动打开应用,同时在程序界面上弹出刚才输入的文字内容。     ### 2,样例代码 ### 2,样例代码
(1)NotificationHandler.swift
为方便管理维护,这里我们将通知响应(action 响应)放在一个单独的文件中。并且将通知的 category 和 action 的标识符都定义成枚举。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | importUIKitimportUserNotifications//通知category标识符枚举enumNotificationCategory: String{    casenews  //新闻资讯通知category}//通知category的action标识符枚举enumNotificationCategoryAction: String{    caselike    casecancel    casecomment}//通知响应对象classNotificationHandler: NSObject, UNUserNotificationCenterDelegate{    //对通知进行响应(用户与通知进行交互时被调用)    funcuserNotificationCenter(_ center: UNUserNotificationCenter,                                didReceive response: UNNotificationResponse,                                withCompletionHandler completionHandler:        @escaping() -> Void) {        //根据category标识符做相应的处理        letcategoryIdentifier = response.notification.request.content.categoryIdentifier        ifletcategory = NotificationCategory(rawValue: categoryIdentifier) {            switchcategory {            case.news:                handleNews(response: response)            }        }        completionHandler()    }        //处理新闻资讯通知的交互    privatefunchandleNews(response: UNNotificationResponse) {        letmessage: String                //判断点击是那个action        ifletactionType = NotificationCategoryAction(rawValue: response.actionIdentifier) {            switchactionType {            case.like: message = "你点击了“点个赞”按钮"            case.cancel: message = "你点击了“取消”按钮"            case.comment:                message = "你输入的是:\((response as! UNTextInputNotificationResponse).userText)"            }        } else{            //直接点击通知,或者点击删除这个通知会进入这个分支。            message = ""        }                //弹出相关信息        if!message.isEmpty {            showAlert(message: message)        }    }        //在根视图控制器上弹出普通消息提示框    privatefuncshowAlert(message: String) {        ifletvc = UIApplication.shared.keyWindow?.rootViewController {            letalert = UIAlertController(title: nil, message: message, preferredStyle: .alert)            alert.addAction(UIAlertAction(title: "确定", style: .cancel))            vc.present(alert, animated: true)        }    }} | 
(2)AppDelegate.swift
这里除了申请通知权限外,还注册了一个 category,里面包括两个标准按钮 action,以及一个文本输入 action。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | importUIKitimportUserNotifications@UIApplicationMainclassAppDelegate: UIResponder, UIApplicationDelegate{        varwindow: UIWindow?        letnotificationHandler = NotificationHandler()        funcapplication(_ 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                returntrue    }        funcapplicationWillResignActive(_ application: UIApplication) {    }        funcapplicationDidEnterBackground(_ application: UIApplication) {    }        funcapplicationWillEnterForeground(_ application: UIApplication) {    }        funcapplicationDidBecomeActive(_ application: UIApplication) {    }        funcapplicationWillTerminate(_ application: UIApplication) {    }        //注册一个category    privatefuncregisterNotificationCategory() {        letnewsCategory: UNNotificationCategory= {            //创建输入文本的action            letinputAction = UNTextInputNotificationAction(                identifier: NotificationCategoryAction.comment.rawValue,                title: "评论",                options: [.foreground],                textInputButtonTitle: "发送",                textInputPlaceholder: "在这里留下你想说的话...")                        //创建普通的按钮action            letlikeAction = UNNotificationAction(                identifier: NotificationCategoryAction.like.rawValue,                title: "点个赞",                options: [.foreground])                        //创建普通的按钮action            letcancelAction = UNNotificationAction(                identifier: NotificationCategoryAction.cancel.rawValue,                title: "取消",                options: [.destructive])                        //创建category            returnUNNotificationCategory(identifier: NotificationCategory.news.rawValue,                                          actions: [inputAction, likeAction, cancelAction],                                          intentIdentifiers: [], options: [.customDismissAction])        }()                //把category添加到通知中心        UNUserNotificationCenter.current().setNotificationCategories([newsCategory])    }} | 
(3)ViewController.swift
我们在程序界面打开后就创建通知(5 秒后推送)。特别注意的是要将通知的 categoryIdentifier 设置为需要的 category 标识符,这样系统就知道这个通知对应的是哪个 category。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | importUIKitimportUserNotificationsclassViewController: UIViewController{        overridefuncviewDidLoad() {        super.viewDidLoad()                //设置推送内容        letcontent = UNMutableNotificationContent()        content.title = "hangge.com"        content.body = "囤积iPhoneX的黄牛赔到怀疑人生?"        //设置通知对应的category标识符        content.categoryIdentifier = NotificationCategory.news.rawValue                //设置通知触发器        lettrigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)                //设置请求标识符        letrequestIdentifier = "com.hangge.testNotification"                //设置一个通知请求        letrequest = UNNotificationRequest(identifier: requestIdentifier,                                            content: content, trigger: trigger)                //将通知请求添加到发送中心        UNUserNotificationCenter.current().add(request) { error in            iferror == nil{                print("Time Interval Notification scheduled: \(requestIdentifier)")            }        }    }        overridefuncdidReceiveMemoryWarning() {        super.didReceiveMemoryWarning()    }} | 
源码下载: hangge_1845.zip
hangge_1845.zip
3,远程推送使用 category
远程推送也可以使用 category,只需要在 payload 报文中添加 category 字段,并指定预先定义的 category id 就可以了。
| 1 2 3 4 5 6 7 8 9 10 11 | {  "aps":{    "alert":{      "title":"hangge.com",      "body":"囤积iPhoneX的黄牛赔到怀疑人生?"    },    "sound":"default",    "badge":1,    "category":"news"  }} | 
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 叶落花开的博客!
 评论