[iOS 10 day by day] Day 6:自定义的通知界面

续上篇,在简单闹钟的例子上,在通知界面上显示图片动画,并用通知关联的按钮更新通知界面。介绍 iOS 10 通知 API 的扩展:自定义通知显示界面。

《iOS 10 day by day》是 shinobicontrols 公司编写的系列博客,介绍开发者需要了解的 iOS 10 新特性,每周更新。本系列翻译(文集地址)已取得官方授权。目录点此。仓薯翻译,欢迎指正:)

Shinobicontrols 为 iOS 和 Android 开发者提供高性能、响应式的 UI 控件 SDK,尤其是图表方面的控件。 官网 : shinobicontrols.com twitter : @shinobicontrols

我们在 Day 5 中介绍了新的 UserNotifications 框架。新框架可以统一处理本地通知和远程推送,同时增加了一些新 API 来控制等待中和已发出的通知。

以上这些都很棒,不过苹果还在通知方面更进一步,让开发者能添加一个自定义的通知界面,用户收到通知之后可以选择查看这个自定义界面。要实现这个功能,需要添加一个单独的 UserNotificationsUI 框架。这个框架的 API 特别简单,只含有一个公共的 protocol:UNNotificationContentExtension

工程

我们的样例工程是在上一篇文章的闹钟 app 基础上,增加了一个炫酷的自定义通知界面。通过这个界面,用户可以不用切换到闹钟 app 就能直接取消通知。先来看下效果:

11227290-0c09d911ff05670f

自定义通知界面效果

跟所有 Day by Day 系列文章一样,工程源码放在了 Github 上。

创建 Extension

iOS 10 的许多旗舰功能都是建立在苹果的 Extension 架构上的。前面的系列文章 Xcode 插件iMessage 插件 都是如此。而自定义通知界面也是用同样的方法实现的。

首先,我们要给闹钟 app 的工程加一个新的 target。在下面这个选择 target 模板的界面,选择 Notification Content。然后随便起个名字,我用的是 NagMeContentExtension

12227290-457495502483a4e0

选择 target 模板

你可能会注意到,除了默认的Info.plist之外,这个 extension 还包含另外两个文件:

  • MainInterface.storyboard : 我们把自定义通知界面的 UI 画在这里
  • NotificationViewController.swift : 一个 UIViewController 的子类,这就是自定义界面的 ViewController,我们通过这个类来管理自定义的界面。

把 Extension 与通知 category 关联起来

现在工程设置好了,我们需要让系统知道,是哪个通知要展示这个界面。不知道你记不记得,上一篇文章讲过,一个 category 就是一个很简单的对象(参考 UNNotificationCategory),里面定义了你的 app 支持哪些类型的通知,以及每种通知关联了什么操作——就是用户把通知展开的时候,通知下面出现的那些操作按钮。

具体实现这一步,需要打开 extension 的 Info.plist,展开 NSExtensionAttributes Dictionary,把下面 UNNotificationExtensionCategory 这个键对应的值改为通知 category 的名字(“reminder”)。注意,这个值既可以填一个 string ,也可以填一个 string 数组,如果想让多个通知 category 共用一个 extension 界面就可以填 string 数组。

13227290-9b24c7f12530f35a

Info.plist

现在把工程 Build、Run 一下,我们可以看到一个比默认的通知弹框更有意思一点的界面。

14227290-a353d8b38a265c5d

extension 的默认界面

管用了!现在用的是 extension 默认的 MainInterface.storyboard 界面,然后是 NotificationViewController 里的模板代码在更新界面上的 label。不过这个界面还是有几点需要改进的地方。首先,通知的内容(”Walk Dog!!”)在 extension 的界面上和 DefaultContent 区域重复出现了两次。我们先把这个重复的去掉吧!

去掉 DefaultContent

很简单,只需在 Info.plist 文件里的 NSExtensionAttributes 下面增加一个 key ,UNNotificationExtensionDefaultContentHidden,然后值设为 YES,就不会显示 DefaultContent 了。

15227290-92ea97efc85da478

去掉 default content 之后

好,下面我们来写自定义的界面吧。

自定义的通知界面

切换到 MainInterface.storyboard,加上 UI 控件。加一个 label 描述提醒的事项,加一个小喇叭的图片。加完之后,只需拖几个 IBOutlets 出来,就大功告成啦!

收到通知的时候,我们要更新 label 上的文本,同时摇晃小喇叭的图片——用这种粗暴的方式吸引用户的注意力。要实现这些功能,需要在 NotificationViewController 里进行一些修改。我们的 viewController 实现了 UNNotificationContentExtension 这个 protocol,下面用到的就是这个 protocol 中定义的方法:

这个方法就是收到通知之后,根据通知内容来配置通知界面的指定方法。

16227290-6c1c7886eec1875c

初步的通知界面

看起来还不错,但是中间有一大段空白,看上去不大美观。

幸运的是,要解决这个问题只需加 Info.plist 里再加一个 key UNNotificationExtensionInitialContentSizeRatio,它定义了自定义通知界面的高宽比。这个值可能需要多试几次来调整,对于我们目前的情况取 0.5 就比较合适了(当宽度是 300 的时候,高度是 150)。

17227290-c6a3ef31d3366d9c

调整高宽比之后的界面

NotificationViewController 就是一个单纯的 UIViewController 的子类,用起来跟你平常在主 app 里用普通的 viewController 是一样的。唯一的不同点在于它的 userInteraction 是 disabled 的,意思是完全无法接收到用户的点击、触摸事件。所以有部分控件是用不了的,比如 UIScrollView、UIButton 等。

接受用户操作

自定义的界面我们画出来了,但是还有一点要改进:点击 “Cancel” 按钮,只会让用户切回到闹钟 app,这一步有点多余。

上一篇文章我们讲了怎么给通知加上操作按钮:通知出现时可以进行的每一项操作都是一个 UNNotificationAction,关联在通知 category 上。更详细的介绍可以参考官方文档

UNNotificationContentExtension 这个 protocol 提供了另一个处理点击事件的方法:didReceive(_:completionHandler:)。我们就用这个方法,把小喇叭的 icon 改成红线划掉的小喇叭,然后把通知从 UNNotificationCenter 中移除。

相关的通知都移除了,UI 也更新了,接下来我们需要告诉系统该怎么处置这个通知界面。因为我们想让用户看到被划掉的小喇叭,得到通知被取消的视觉反馈,所以要把通知留在屏幕上,因此回调里传入 UNNotificationContentExtensionResponseOption 的一个取值 .doNotDismiss

18227290-8ceac0cb657dfe5d

取消通知

既然要用这个方法处理点击,就得处理好每一个按钮事件。在这个例子里,我们只有一个“Cancel”按钮。然而,如果还有别的按钮,它们的点击事件也需要处理好:要么也在 extension 工程的这个方法里处理,要么回调传 UNNotificationContentExtensionResponseOption.dismissAndForwardAction,传给主 app 去处理。

扩展阅读

UserNotificationsUI 这个框架并没有什么惊天动地的突破,但它能让用户与 app 的交互更便捷。用户可以直接对通知进行操作,不用再切换到发出通知的 app 了;甚至通知界面的 UI 也能动态改变,来更好地反馈用户操作的结果。

关于通知的其他“高级”特性,我推荐看看 WWDC 2016 的演讲视频。这场视频中,演讲者给出了几个苹果官方 app 自定义通知界面的例子,比如接收日程邀请。

1 3 收藏 评论

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部