美文网首页
Swift - UserNotifications框架使用详解7

Swift - UserNotifications框架使用详解7

作者: 小旗_96e8 | 来源:发表于2020-05-05 17:51 被阅读0次

    iOS 10 中添加了两个与通知相关的 extension:Service Extension 和 Content Extension。前者我在上文中已经介绍过了,本文介绍下后者:可以用来自定义通知的详细页面视图的 Content Extension。

    十五、创建 Notification Content Extension

    1,操作步骤

    (1)首先我们点击"File" -> "New" -> "Target...",使用 NotificationContent 的模板来创建一个 NotificationContent。

    (2)使用模版创建完毕后,会自动生成如下三个文件:

    (3)NotificationViewController.swift

    这个是一个实现了 UNNotificationContentExtension 的 UIViewController 子类。

    该 extension 中有一个必须实现的方法 didReceive(_:)。当系统需要显示自定义样式的通知详情视图时,这个方法将被调用,然后我们可以在其中配置更新我们的 UI。

    默认生成的代码如下:直接将通知内容显示在 label 中。我们先不做修改。

    import UIKit

    import UserNotifications

    import UserNotificationsUI

    class NotificationViewController: UIViewController, UNNotificationContentExtension {

        @IBOutlet var label: UILabel?

        override func viewDidLoad() {

            super.viewDidLoad()

        }

        func didReceive(_ notification: UNNotification) {

            self.label?.text = notification.request.content.body

        }

    }

    (4)MainInterface.storyboard

    这里定义了该 extension 对应的详情视图 UI。

    默认生成的 UI 如下:只有一个 label 文本标签。我们先不做修改。

    (5)Info.plist

    这里指定了该 extension 的各种配置。我们可以通过 Info.plist 控制通知详细视图的尺寸,以及是否显示原始的通知。

    要特别注意的是 UNNotificationExtensionCategory 这个 key 值,它指定这个通知样式所对应的 category 标识符。系统在接收到通知后会通过 category 标识符先查找有没有能够处理这类通知的 content extension,如果存在,那么就交给这个extension 来进行处理。

    默认生成的 category 标识符是 myNotificationCategory。我们先不做修改。

    2,使用样例

    (1)下面代码在页面加载完毕后会自动创建个 5 秒后的推送通知。注意的是我们将通知的 categoryIdentifier 设置成上面 content extension 的 category 标识符。

    import UIKit

    import UserNotifications

    class ViewController: UIViewController {

        override func viewDidLoad() {

            super.viewDidLoad()

            //设置推送内容

            let content = UNMutableNotificationContent()

            content.title = "hangge.com"

            content.body = "做最好的开发者知识平台"

            //设置category标识符

            content.categoryIdentifier = "myNotificationCategory"

            //设置通知触发器

            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()

        }

    }

    (2)可以看到通知的详情视图已经变成我们自定义的视图了。

    十六、自定义通知详情视图(并添加 UI 交互功能)

    1,效果图

    (1)这里我们推送一条使用自定义详情视图的通知,这个通知里其实包含了三条新闻资讯。

    (2)打开通知详情时,会显示第一条资讯的标题、内容摘要、以及相关图片。下方还有三个交互按钮:

    点击“换一条”按钮,这个通知视图会继续显示,不过内容会切换成下一条资讯。

    点击“打开”按钮,则自动打开应用。我们可以在程序中进行下一步操作,比如打开对应的新闻详情页面。

    点击”取消“按钮,则自动清除通知,且不会打开应用。

    2,Notification Content Extension 配置

    (1)MainInterface.storyboard

    这里我们在视图上添加两个 Label 和一个 ImageView,分别用来显示新闻资讯的标题、内容摘要、以及图片。

    同时还要设置好各个组件的约束,并在代码中做好 @IBOutlet 关联。

    (2)NotificationViewController.swift

    我们在这里对详情视图进行显示和更新操作。特别注意的是,虽然我们可以使用包括按钮在内的各种 UI 组件,但是系统不允许我们与这些 UI 进行交互。点击通知视图本身会直接将我们导航到应用中,因此我们需要通过 action 按钮的方式来对视图进行更新。

    didReceive(_:completionHandler:)方法介绍:

    它是 UNNotificationContentExtension 的一个可选方法,它会在用户选择了某个 action 时被调用。我们可以根据情况给 completionHandler 传递不同的值实现不同操作:

    如果需要更新详情视图,可以选择传递 .doNotDismiss 来保持通知继续被显示。

    如果没有继续显示的必要,传递 .dismissAndForwardAction 会打开应用,并把通知的 action 继续传递给应用的 UNUserNotificationCenterDelegate 中的 userNotificationCenter(:didReceive:withCompletionHandler)

    而传递 .dismiss则直接将这个通知清除,同时也不会打开这个应用。

    import UIKit

    import UserNotifications

    import UserNotificationsUI

    //资讯条目

    struct NewsItem {

        let title: String

        let abstract: String

        let url: URL

    }

    class NotificationViewController: UIViewController, UNNotificationContentExtension {

        //显示资讯标题

        @IBOutlet var titleLabel: UILabel!

        //显示资讯内容摘要

        @IBOutlet weak var abstractLabel: UILabel!

        //显示资讯图片

        @IBOutlet weak var imageView: UIImageView!

        //当前显示的资讯索引

        private var index: Int = 0

        //所有资讯条目

        var items: [NewsItem] = []

        override func viewDidLoad() {

            super.viewDidLoad()

        }

        //收到通知

        func didReceive(_ notification: UNNotification) {

            //处理资讯条目

            let content = notification.request.content

            if let news = content.userInfo["news"] as? [[String: String]] {

                for i in 0..<news.count {

                    let title = news[i]["title"] ?? ""

                    let abstract = news[i]["abstract"] ?? ""

                    let url = content.attachments[i].url

                    let presentItem = NewsItem(title: title, abstract: abstract, url: url)

                    self.items.append(presentItem)

                }

            }

            //显示第一条资讯

            updateNews(index: 0)

        }

        //更新显示的资讯内容

        private func updateNews(index: Int) {

            let item = items[index]

            //更新标题和内容摘要

            self.titleLabel!.text = item.title

            self.abstractLabel.text = item.abstract

            //更新图片

            if item.url.startAccessingSecurityScopedResource() {

                self.imageView.image = UIImage(contentsOfFile: item.url.path)

                item.url.stopAccessingSecurityScopedResource()

            }

            self.index = index

        }

        //Action按钮点击响应

        func didReceive(_ response: UNNotificationResponse, completionHandler completion:

            @escaping (UNNotificationContentExtensionResponseOption) -> Void) {

            if response.actionIdentifier == "change" {

                //切换下一条资讯

                let nextIndex = (index + 1) % items.count

                updateNews(index: nextIndex)

                //保持通知继续被显示

                completion(.doNotDismiss)

            } else if response.actionIdentifier == "open" {

                //取消这个通知并继续传递Action

                completion(.dismissAndForwardAction)

            } else if response.actionIdentifier == "dismiss" {

                //直接取消这个通知

                completion(.dismiss)

            } else {

                //取消这个通知并继续传递Action

                completion(.dismissAndForwardAction)

            }

        }

    }

    (3)extension 的 Info.plist

    通知扩展对应的 category 标识符这里不做修改。主要修改下 UNNotificationExtensionInitialContentSizeRatio 这个 key 值,它是 UI 界面默认的高宽比,将其修改成 0.8,这样在界面出来的时候不会有很突兀的 frame 改变。

    3,Notification Content Extension 使用

    (1)AppDelegate.swift

    这里要注意的是我们注册一个通知 category,里面包含三个 Action 按钮。

    import UIKit

    import UserNotifications

    @UIApplicationMain

    class AppDelegate: UIResponder, UIApplicationDelegate {

        var window: UIWindow?

        func application(_ application: UIApplication, didFinishLaunchingWithOptions

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

            UNUserNotificationCenter.current()

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

                    (accepted, error) in

                if !accepted {

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

                }

            }

            //注册category

            registerNotificationCategory()

            return true

        }

        func applicationWillResignActive(_ application: UIApplication) {

        }

        func applicationDidEnterBackground(_ application: UIApplication) {

        }

        func applicationWillEnterForeground(_ application: UIApplication) {

        }

        func applicationDidBecomeActive(_ application: UIApplication) {

        }

        func applicationWillTerminate(_ application: UIApplication) {

        }

        //注册一个category

        private func registerNotificationCategory() {

            let newsCategory: UNNotificationCategory = {

                //创建三个普通的按钮action

                let changeAction = UNNotificationAction(

                    identifier: "change",

                    title: "换一条",

                    options: [])

                let openAction = UNNotificationAction(

                    identifier: "open",

                    title: "打开",

                    options: [.foreground])

                //创建普通的按钮action

                let cancelAction = UNNotificationAction(

                    identifier: "cancel",

                    title: "取消",

                    options: [.destructive])

                //创建category

                return UNNotificationCategory(identifier: "myNotificationCategory",

                                              actions: [changeAction, openAction, cancelAction],

                                              intentIdentifiers: [], options: [])

            }()

            //把category添加到通知中心

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

        }

    }

    (2)ViewController.swift

    我们同样是页面打开后就推送个 5 秒后的通知。注意的是这里会给通知添加附加信息(包含资讯标题和内容摘要),以及资讯使用的图片附件。

    import UIKit

    import UserNotifications

    class ViewController: UIViewController {

        override func viewDidLoad() {

            super.viewDidLoad()

            //设置推送内容

            let content = UNMutableNotificationContent()

            content.body = "今日资讯精选【2017-12-12】"

            //设置通知category标识符

            content.categoryIdentifier = "myNotificationCategory"

            //设置通知附件图片

            let imageNames = ["image1", "image2", "image3"]

            let attachments = imageNames.flatMap { name -> UNNotificationAttachment? in

                if let imageURL = Bundle.main.url(forResource: name, withExtension: "png") {

                    return try? UNNotificationAttachment(identifier: "\(name)", url: imageURL,

                                                         options: nil)

                }

                return nil

            }

            content.attachments = attachments

            //设置通知附加信息(资讯标题和内容摘要)

            content.userInfo = ["news": [

                ["title": "全国人民喜迎油价上涨",

                 "abstract": "据国内多家测评机构的分析,国内成品油零售限价将迎来“两连涨”..."],

                ["title": "房价同比下降城市大幅扩容",

                 "abstract": "70个大中城市中一二三线城市房价同比涨幅继续回落。这意味着,往年..."],

                ["title": "比特币市值再创新高",

                 "abstract": "一项名为SegWit2X的技术取消升级,导致在本周一比特币市值蒸发多达380亿美元..."]

                ]]

            //设置通知触发器

            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()

        }

    }

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

    相关文章

      网友评论

          本文标题:Swift - UserNotifications框架使用详解7

          本文链接:https://www.haomeiwen.com/subject/yxqvghtx.html