图片
.1
Apple Watch
编程指南
前言
本教程翻译自
Apple
官方发行的
Apple Watch Programming Guide
编程指南,为开发者提供权威的编程指导。
本教程关于使用
API
以及相关技术的初步文档,苹果提供此文档便于你在苹果的相关产品上开发应用软件。后期该文档会有所变动,所以依据本文档开发的应用软件应当使用最新的
操作系统进行测试,该文档的新版本会进一步提供
API
以及相关技术支持。
1
概述
开发您的
Watch
应用
>
重要提示
这是一篇关于使用
API
以及相关技术的初步文档,苹果提供此文档便于你在苹果的相关产品上开发应用软件。后期该文档会有所变动,所以依据本文档开发的应用软件应当使用最新
的操作系统进行测试,该文档的新版本会进一步提供
API
以及相关技术支持。
Apple Watch
给用户呈现了一种人性化,极为容易的获取信息的方式。相较于从口袋里掏出
iPhone
而言,直接看一眼
Apple Watch
来查看信息更加便利。所以,给
Apple Watch
编写的
应用程序需要具备极为简易的交互流程,尽可能简单而直白的操作方式。
图片
1.1
image
Apple Watch
的运行需要配合
iPhone
运行对应的第三方应用。创建第三方应用需要两个不同的可执行文件:在
Apple Watch
上运行的
Watch
应用,以及在用户
iPhone
上运行的
WatchKit
应用扩展。
Watch
应用只包含与应用程序的用户界面相关的
storyboards
以及资源文件。
WatchKit
应用扩展则包含了用于管理、监听应用程序的用户界面以及响应用户交互的代码。借助
这两个可执行程序,您可以在
Apple Watch
上运行不同类型的用户界面:
•
Watch
应用拥有
iOS
应用的完整用户界面。用户从主界面启动手表应用,来查看或处理信息。
•
使用
glance
界面以便在
Watch
应用上显示即时、相关的信息,该界面是可选的只读界面。并不是所有的
Watch
应用都需要使用
glance
界面。
•
自定义通知界面可以让您修改默认的本地或远程通知界面,并可以添加自定义控件,内容以及设置风格。自定义通知界面是可选的。
Watch
应用需要尽可能实现
Apple Watch
提供的所有交互动作。由于
Watch
应用目的在于扩展
iOS
应用的功能,因此
Watch
应用和
WatchKit
应用扩展将被捆绑在一起,并且都会被打包
进
iOS
应用包当中。如果用户有与
iOS
设备配对了
Apple Watch
,那么随着
iOS
应用的安装,系统将会提示用户安装相应的
Watch
应用。
Watch
应用
Watch
应用是在
Apple Watch
上交互的主体。
Watch
应用通常是从
Apple Watch
的主屏幕上访问,并且能够提供一部分关联
iOS
应用的功能。
Watch
应用的目的在于让用户快速浏览相关
数据。
Watch
应用与
iPhone
上运行的
WatchKit
应用(扩展)协同工作,它不包含任何自定义代码,仅仅只是存储了故事板以及和用户界面相关联的资源文件。
WatchKit
应用扩展是实现这些操作的核心所在。它包含了页面逻辑以及用来管理内容的代码,实现用户操作响应,并且刷新用户界面。由于应用扩展是在用户的
iPhone
上运行,因此
它能轻易地和
iOS
应用协同工作,比如说收集坐标位置或者执行其他长期运行任务。
要开始创建
Watch
应用,请参考:
App Essential
创建
Glance
界面
Glance
是一个展示即时重要信息的界面。
glance
中的内容应当言简意赅,因为其目的是让用户迅速地查看消息。
Glance
不支持滚动,因此整个
glance
界面只能在单个界面上显示,您
需要保证它拥有合适的大小。
glance
只读,因此不能包含按钮、开关,或者其它交互动作。点击
glance
则会直接启动您的
Watch
应用。
您需要在
WatchKit
应用扩展中添加管理
glance
的代码,用来管理
glance
界面的类与
Watch
应用的类相同。即便如此,创建
glance
更容易实现,因为其无需响应用户交互动作。
要开始创建
glance
界面,请参阅:
Glance Essentials
自定义通知界面
Apple Watch
能够和与之配对的
iPhone
协同工作,来显示本地或者远程通知。
Apple Watch
首先使用一个小窗口来显示通知信息。当用户移动手腕希望看到更多的信息时,这个小窗口
便会显示更详细的通知内容。应用可以提供详情界面的自定义版本,并且可以添加自定义控件或者改变系统默认的通知信息。
Apple Watch
支持
iOS 8
中引入的交互式通知。交互式通知通过在通知上添加按钮来让用户立即做出回应。比如说,一个日历时间通知可能会包含了接收或拒绝某个会议邀请的按钮。
只要你的
iOS
应用支持交互式通知,那么
Apple Watch
就会自行向自定义或默认通知界面上添加合适的按钮。你所需要做的只是在
WatchKit
应用扩展中处理这些事件而已。
要开始创建自定义通知界面,请参阅:
Notification Essentials
配置
Xcode
项目
Xcode
会将
Watch
应用和
WatchKit
应用扩展一起打包,然后放进现有的
iOS
应用包中。
Xcode
提供了一个搭建
Watch
应用的模板,其中包含了创建应用、
glance
,以及自定义通知界面
所需的所有资源。你可以在项目中进行实时测试。
Xcode
中的
WatchKit
应用包已经包含了所有你需要的资源来创建出
WatchKit
应用。包括
glances
,自定义通知界面。并且
iOS
模拟器提供了一个实时环境来测试它的界面以及所有的接
口。
>
重要提示
WatchKit
开发环境需要
iOS 8.2
以上的
SDK
,请在
developer.apple.com
获取最新
SDK
。
向
iOS
应用中添加
Watch
应用
要向现有项目中添加
Watch
应用对象,请执行以下操作:
1.
打开现有的
iOS
应用项目
2.
选择
File > New > Target
,然后选中
Apple Watch
3.
选择
Watch App
,然后单击
Next
4.
如果您想要使用
glance
或者自定义通知界面,请选择相应的选项我们建议您激活应用通知选项。选中之后就会创建一个新的文件来调试该通知界面。如果您没有选择这个选项,
那么之后您只能手动创建这个文件了。
5.
单击
Finish
完成上述操作之后,
Xcode
将
WatchKit
应用扩展所需的文件以及
Watch
应用添加到项目当中,并自动配置相应的设置。
Xcode
将基于
iOS
应用的
bundle ID
来为两个新对象设置它们的
bundle ID
。比如说,
iOS
应用的
bundle ID
为
com.example.MyApp
,那么
Watch
应用的
bundle ID
将被设置为
com.example.MyApp.watchapp
,
WatchKit
应用扩展的
bundle ID
被设置为
com.example.MyApp.watchkitextension
。这三个可执行对象的基本
ID
(即
com.example.MyApp
)必须相匹配,如果您更改了
iOS
应用的
bundle ID
,那么您就必须相应的更改另外
两个对象的
bundle ID
。
应用软件结构
Xcode
中的
WatchKit
应用扩展模板为
iOS
应用创建了两个新的可执行程序。
Xcode
同时也配置了项目的编译依赖,从而让
Xcode
在编译
iOS
应用的同时也编译这两个可执行文件。
图
2-1
说明了它们的依赖关系,并解释了
Xcode
是如何将它们打包在一起的。
WatchKit
依赖于
iOS
应用,而其同时又被
Watch
应用依赖。编译
iOS
应用将会将这三个对象同时编译并
打包。
图
2-1
Watch
应用对象的结构
图片
1.2
Watch
应用对象的结构
编译、运行以及调试程序
当您创建完
Watch
应用对象后,
Xcode
将自行配置用于运行和调试应用的编译方案。使用该配置在
iOS
模拟器或真机上启动并运行您的应用。
对于包含
glance
或者自定义通知的应用来说,
Xcode
会分别为其配置不同的编译方案。使用
glance
配置以在模拟器中调试
glance
界面,使用通知配置以测试静态和动态界面。
为
glance
和通知配置自定义编译方案
1
、选择现有的
Watch
应用方案
2
、从方案菜单中选择
Edit Scheme
图片
1.3
image
3
、复制现有的
Watch
应用方案,然后给新方案取一个合适的名字。
比如说,命名为
“Glance - My Watch app”
,表示该方案是专门用来运行和调试
glance
。
4
、选择方案编辑器左侧栏的
Run
选项
5
、在信息选项卡中,选择合适的可执行对象
图片
1.4
image
6
、关闭方案编辑器以保存更改
指定一个通知进行测试
当您在
iOS
模拟器调试自定义通知界面的时候,您可以指定一个
JSON
负载来模拟推送的通知。通知界面的
Xcode
模板包含一个
RemoteNotificationPayload.json
文件,您可以用它来指
定负载中的数据。这个文件位于
WatchKit
应用扩展的
Supporting Files
文件夹。只有当您在创建
Watch
应用时勾选了通知场景选项,这个文件才会被创建。如果这个文件不存在,您可
以用一个新的空文件手动创建它。
RemoteNotificationPayload.json
文件包含了绝大多数您需要的键值,但是您可以根据应用程序的实际情况添加更多的键值。图
2-2
展示了项目中的默认
JSON
文件。由于
iOS
模
拟器无法访问
iOS
应用的注册动作,这个负载便包含了一个名为
“WatchKit Simulator Actions”
的键值,其值为一个包含了一系列动作的数组。每个动作按钮含有
title
和
identifier
键,它们的值和
iOS
应用中注册的相应键值相同。
图
2-2
一个模拟的远程通知负载
图片
1.5
一个模拟的远程通知负载
绝大部分的
JSON
数据会在运行时打包进字典中进行传输。因为
iOS
模拟器没办法处理
iOS
应用的预置动作。您也许需要负载文件来指定您的动作。
WatchKit
模拟器包含了一个行为
的数组。数组中的每一个元素包含了以下内容:
•
标题
-
行为的标题,必须包含这个键值
•
id
标示
-
用来传递你的视图控制器的
application:handleActionWithIdentifier:forLocalNotification:completionHandler:
或者
application:handleActionWithIdentifier:forRemoteNotification:completionHandler:
,必须包含这个键值
•
destructive
-
这个键值包含两个值,
1
或
0
,
1
会导致按钮被渲染成
destructive
的样式。
0
会导致按钮被渲染成普通模式,这个键值是可选的。
为了用
JSON
负载测试您的通知接口,您需要用
appropriate
负载文件来配置
build scheme
。当您选择了一个通知接口的可执行文件,
Xcode
会添加一个菜单来选择您的负载文件。您可
以用不同的
build schemes
来加载不同的配置文件,或者您也可以修改以前的负载文件来达到更新的目的。
Watch
应用结构
Apple Watch
应用程序包含两个部分:
Watch
应用和
WatchKit
应用扩展。
Watch
应用驻留在用户的
Apple Watch
中,只含有故事板和资源文件,要注意它并不包含任何代码。而
WatchKit
应用扩展驻留在用户的
iPhone
上(在关联的
iOS
应用当中),含有相应的代码和管理
Watch
应用界面的资源文件。
当用户开始与
Watch
应用交互时,
Apple Watch
将会寻找一个合适的故事板场景来显示。它根据用户是否在查看应用的
glance
界面,是否在查看通知,或者是否在浏览应用的主界面等
行为来选择相应的场景。选择完场景后,
Watch OS
将通知配对的
iPhone
启动
WatchKit
应用扩展,并加载相应对象的运行界面。所有的消息交流都在后台进行。
图
3-1
Watch
应用和
WatchKit
应用扩展之间的通信
图片
1.6
Watch
应用和
WatchKit
应用扩展之间的通信
场景管理:界面控制器
您
Watch
应用的构建模块是界面控制器,它是
WKInterfaceController
类的实例。
WatchKit
中的界面控制器用来模拟
iOS
中的视图控制器:它显示、管理屏幕上的内容,并且响应用户交
互。
如果用户直接启动您的应用,系统将从主故事板文件中加载初始界面控制器。根据用户的交互,您可以显示其他界面控制器以让用户得到需要的信息。如何显示额外的界面控制器取决
于您应用所使用的界面样式。
WatchKit
支持基于页面的风格以及基于层次的风格。这两个风格不能共存的,要了解更多信息,请参阅:
Interface Navigation
。
>
重要提示
Glances
和通知只会显示一个包含相关信息的界面控制器。用户与界面控制器的交互操作会展示应用的主界面。要了解如何实现
glance
,请参阅
Glance Essentials
。要了解自定义通知界
面,请参阅:
Notification Essentials
。
Watch
应用的生命周期
Apple Watch
上的用户交互将启动您的应用并驱动其生命周期。当用户在
Apple Watch
上运行您的应用时,用户的
iPhone
会自行启动相应的
WatchKit
应用扩展。通过一系列的信号交
换,
Watch
应用和
Watch
应用扩展将互相连接,因此消息能够在二者之间流通,直到用户停止与应用进行交互为止。此时,
iOS
将暂停应用扩展的运行。
随着启动序列的运行,
WatchKit
自动为当前界面创建相应的界面控制器。如果用户正在查看
glance
,
WatchKit
创建出来的界面控制器将与
glance
相连接。如果用户直接启动您的应
用,
WatchKit
将从应用的主故事板文件中加载初始界面控制器。无论哪种情况,
WatchKit
应用扩展都提供一个名为
WKInterfaceController
的子类来管理相应的界面。
界面控制器对象初始化后,您就应当为其准备显示相应的界面。图
3-2
展示了
Watch
应用的启动序列。当应用启动时,
WatchKit
框架自行创建了相应的
WKInterfaceController
对象
并调用
initWithContext:
方法。使用该方法来初始化界面控制器,然后加载所需的数据,最后设置所有界面对象的值。对主界面控制器来说,初始化方法紧接着
willActivate
方法运行,
以让您知道界面已显示在屏幕上。了解更过,请参阅
App Essentials
。
图
3-2
启动
Watch
应用
图片
1.7
启动
Watch
应用
当用户在
Apple Watch
上与应用进行交互时,
WatchKit
应用扩展将保持运行。如果用户明确退出应用或者停止与
Apple Watch
进行交互,那么
iOS
将停用当前界面控制器,并暂停应用
扩展的运行,如图
3-3
所示。与
Apple Watch
的互动是非常短暂的,因此这几个步骤都有可能在数秒之间发生。所以,界面控制器应当尽可能简单,并且不要运行长时任务。重点应当
放在读取和显示用户想要的信息上来。
>
重要提示
Glance
界面不支持触摸事件响应。点击你的
glance
界面会直接进入加载应用软件。
您的
Watch Kit
扩展包只有在用户正在触发
Watch
上的事件的时候才会响应。这意味着与您的
Watch
进行数据交互会非常的简短,所以,视图控制器需要尽可能的轻量级,且不能执行
耗时的任务。当用户退出了您的应用软件,或者是中断了与
Watch
的交互。
iOS
会检测到当前的视图控制器,然后挂起您的操作。
图
3-3
界面控制器的生命周期
图片
1.8
界面控制器的生命周期
应用各阶段生命周期中执行的任务
在应用生命周期的不同阶段,
iOS
将会调用
WKInterfaceController
对象的相关方法来让您做出相应的操作。表
3-1
列出了大部分您应当在界面控制器中声明的主要方法。
表
3-1
WKInterfaceController
的主要方法
方法
方法的用途
init
初始化你的视图控制器。
awakeWithContext:
这个方法用来准备显示界面。借助它来加载数据,以及更新标签、图像和其他在故事板场景上的界面对象。
willActivate
这个方法可以让您知道该界面是否对用户可视。借助它来更新界面对象,以及完成相应的任务,完成任务只能在界面可视时使用。
方法
方法的用途
didDeactivate
使用
didDeactivate
方法来执行所有的清理任务。例如,使用此方法来废止计时器、停止动画或者停止视频流内容的传输。您不能在这个方法中设置界面控制器对
象的值,在本方法被调用之后到
willActivate
方法再次被调用之前,任何更改界面对象的企图都是被忽略的。
在模拟器上进行测试
测试期间,您可以通过锁定与解锁您的模拟器来验证是否达到了你的预期的效果。当您在使用
Hardware > Lock
命令时,
WatchKit
会调用当前控制器的
didDeactivate
方法。当您解锁了
模拟器,
WatchKit
会执行当前控制器的
willActivate
方法。
与
Containing iOS
应用共享数据
如果您的
iOS
应用和
WatchKit
应用扩展都依赖于相同的数据,那么您可以使用共享程序组来存储数据。共享程序组是一个位于本地文件系统的区域,应用扩展和应用都能够访问。由
于两个程序在不同的沙箱环境中运行,它们一般情况下都不与对方共享文件和进行通信。共享程序组让共享数据成为可能。你可以使用这个空间来存储共享的数据文件或者在两个程序
间交换消息。
您可以在
iOS
应用和
WatchKit
应用扩展中的
Capabilities
选项卡中启动共享程序组。激活这项功能后,
Xcode
将会为每个对象添加授权文件(需要的话),并给那个文件添加
com.apple.security.application-groups
授权。要共享数据,这两个对象必须选择相同的共享程序组。
程序运行时,您可以通过在共享容器目录中读写文件以在两个程序间共享数据。要访问容器,请使用
NSFileManager
中的
containerURLForSecurityApplicationGroupIdentifier:
方法来接
收该目录的根路径。使用方法返回的
URL
来枚举目录内容或者在目录中为文件创建新的
URL
。
与
Containing iOS
应用进行通信
Watch
使用方法
openParentApplication:reply:
来给
iOS
发送请求并等待回复。
WatchKit
扩展包并不支持后台运行;它只会在用户直接主动触碰它时才会响应。
containing iOS
应用在设置
上有许多限制,他可以被配置成后台收集
WatchKit
扩展包的数据的模式。有些事件可能需要额外的时间来完成,例如接收用户定位的数据,这个就需要通过
iOS
来收集数据,然后传
输给
Watch
。
当您使用
openParentApplication:reply:
方法后,
iOS
会在后台启动或者唤醒
containing iOS
应用,然后调用方法
application:handleWatchKitExtensionRequest:reply:
。这个方法会用
提供的字典数据执行请求,然后给
WatchKit
扩展包反馈结果。
使用
iOS
技术
WatchKit
应用扩展可以使用绝大多数
iOS
技术。由于应用扩展和应用还是有一些不同,因此某些技术的使用可能会受到限制,或者不受到推荐。下面是决定是否使用特定技术的准
则:
•
避免使用需要用户权限的技术,比如
Core Location
。
在
WatchKit
应用扩展中使用该技术的话,可能会在您第一次请求使用时导致用户的
iPhone
上显示出一个意想不到的提示。
更糟糕的是,这个状况可能会在任何时间出现,即使用户的
iPhone
在他们的口袋里并且屏幕是锁定的。
•
不要使用后台执行模式的技术。
WatchKit
应用扩展只考虑在前台运行的情况,并且其只在用户和对应的
Watch
应用交互时运行。因此,支持后台运行的某些技术在
WatchKit
应
用扩展中并不被支持。
•
避免使用需要长时间运行的技术。
WatchKit
应用扩展在用户停止和对应的
Watch
应用交互后便迅速暂停。由于与
Watch
应用的交互通常是短暂的,因此应用扩展可能会在请求
的数据到达前暂停运行。
要使用
iOS
技术,其中一种解决方法是让您的
iOS
应用来使用这些技术。例如,在您的
iOS
应用中使用位置服务,而不是在
WatchKit
中使用这个技术。
iOS
应用可以收集所需的数据
然后通过共享程序组来让应用扩展稍后访问。
支持
Handoff
Watch
支持创建的
Handoff
功能。你可以用控制器
WKInterfaceController
中的
updateUserActivity:userInfo:webpageURL:
方法来创建。
在
glance
的控制器中,你可以定制有用的信
息,来与你的设备进行交互。当用户点击了
glance
上的应用的时候,
WatchKit
将会将数据传输到你的设备上。之后,你可以用这个发送过来的数据更新您的设备上的相关内容。
远程控制事件与
Now Playing
信息
Watch
可以用远程控制事件来管你与之配对的
iPhone
,例如播放音乐、视频。设备也会将当前正在播放的音乐(或者视频)信息传输到
Watch
上显示。一个注册过
MPRemoteCommandCenter
的
iOS
应用程序会自动的接受数据处理信息。你不需要在你的
WatchKit
扩展包中做些额外的操作来同步数据。
>
重要提示
为了反馈类似于喜欢、不喜欢或者标记一个内容的信息,
Watch
是使用
localizedShortTitle
,而不是
MPFeedbackCommand
中的
localizedTitle
。
Now Playing
的
glance
会自动的显示当前
iOS
应用的
Now Playing
信息。
iOS
应用程序通过
MPNowPlayingInfoCenter
来提供这些数据。当您的
app
在更新数据时,您应当去更新
nowPlayingInfo
字典的内容。
Watch
会自动的更新数据并显示出来。另外,如果此时用户点击了
Now Playing
上的标题,
Watch
会直接进入
iOS
应用对应的
Watch
应用中。
更多的关于如何实现远程控制以及
Now Playing
的内容,请查阅
Remote Control Events
。
2
WatchKit Apps
UI
概要
开始实现
App
的第一步是定义
Storyboard
中的
Scene
。每个
Scene
定义了整个
App
用户界面的一部分。你可以为不同大小的
Apple Watch
定义不同的
Scene
,也可以为同一个界面配置
不同的展示效果。
布局
Scenes
WatchKit App
使用的布局模型不同于
iOS App
。在
Scene
里面布局
WatchKit App
界面的时候,并没有因为控件的添加而创建多层次的视图层。
Xcode
会决定你所添加到
Scene
中的控件
元素所在的位置,把他们竖直堆叠在不同的行。运行时,
Apple Watch
会取出相应的控件把它们布局在合适的区域并显示出来。
尽管
Xcode
几乎处理了所有的界面布局工作,
Watchkit
也提供了一些让你在
Scene
里面精确控制控件元素的方式。大多数控件的大小和位置可以通过属性面板来设置。控件的位置可以
通过设置控件的水平、竖直方向上的对齐属性来设置。
另外一种控制控件元素位置的方式是组合对象。组合对象可以让你在水平方向和在竖直方向上一样布局控件。组合对象还可以实现在组合范围内保持控件之间间距。组合对象没有默认
的视觉效果,但如果需要的话你也可以配置背景色或是背景图片。
图
5-1
展示了如何在
Storyboard
里面放置不同的控件。前三个控件是标签,每个标签都占满了其所在行的横向区域。对于每个标签,它们的对齐属性决定相对于视图控制器的边界左对
齐、右对齐还是居中。标签的下面是由水平方向上排练的两张图片组成的组合对象。在组合对象的下面还有竖直放置的一条分割线和一个按钮。
图
5-1
Xcode
里的界面对象
在
Xcode
中创建界面的时候,尽可能让控件自适应大小。
App
的界面需要被展示在所有尺寸的
Apple Watch
上。让系统去适配界面,尽量减少为不同设备而写的适配代码。
适配不同的显示尺寸
Xcode
支持为不同大小的
Apple Watch
定义不同的界面。在
Storyboard
里面的改动默认会应用到所有不同大小的
Apple Watch
,你也可以根据需要为不同的设备定义不同的
Scene
。比
如,你可能需要为不同的设备调整控件之间的间距和布局以及设置不同的图片。
为不同大小的设备自定义控件需要用到属性面板上的加号按钮来改变默认的设备信息。点击加号按钮为相应的属性增加对应的设备。改变这个值只会影响当前选中的设备。图
5-2
说明
了如何为
42mm
的
Apple Watch
设置特殊的字体大小。
图
5-2
为不同的设备自定义控件属性
不应该让用户发现你的
App
在不同大小的
Apple Watch
上有不同的界面,因此建议尽可能不要为不同的设备定义不同的界面。尽量限制因间距、边距等改变视图布局的做法。不推荐因
为不同的布局而移除当前界面上所有控件的做法。你应该尽可能为所有的
Apple Watch
使用相似的界面。
如果要预览不同大小设备上的界面效果,用
Storyboard
编辑区域的控制按钮在不同大小设备间切换。
Storyboard
编辑区默认显示任意大小的设备。改变任意大小模式切换到其它所有尺
寸的
Apple Watch
。如果你讲显示模式切换到了某一个具体的大小,此时你所做的改动只会影响该大小对应的设备。
运行时更新界面
运行时,视图控制器可以修改
Scene
中相关对象的以下以下属性:
•
设置或更新数据值。
•
改变控件支持的视觉效果。
•
改变控件的大小。
•
改变控件的透明度。
•
显示、隐藏控件。
不能添加新的控件或是改变已有控件的顺序。尽管你不能移除控件,但是你可以隐藏他们,这样会临时将控件从布局中移除。当所有的控件都隐藏时,其它对象会充满原先这些控件所
在的地方。如果要隐藏某个控件而不让其它对象充满该控件所在的位置,你可以把该控件的
alpha
值设置为
0
。更多关于隐藏控件的内容请参考
Hiding Interface Objects
。
设置
App
的主色
每个
WatchKit App
会有一个相关的主色,这个颜色会在以下
UI
控件上体现出来:
•
状态栏上的标题。
•
通知界面上的
App
名称。
主色存储在
App Storeyboard
里面的一个全局颜色变量里面。要访问这个变量,选中
Storeyboard
,并且选择文件面板。从弹出菜单上选择一个预定义好的颜色,或者用颜色选择器选择
一种自定义的颜色。
界面国际化
和
WatchKit App
关联的
Storyboard
默认就有基本的国际化。会将
Storeyboard
种所有的字符串自动添加到工程的
Localizable.string
文件中。你只需在该文件中将字符串翻译成需要
的语言,然后就可以在
App
中使用了。当运行时创建了一个
Scene
,
Xcode
会将字符串关联上相应的本地化语言。
合理布局界面,以便标签等控件有合适的控件来显示它们的文字。不要把按钮都放在同一行,而是应该把它们竖直放置,以便都有合适的空间显示按钮标题。
至于那些你编码中用到的文本和图片,用类似
iOS
和
OS X App
上国际化的方式:
•
用
NSLocalizedString
宏从资源文件中加载字符串。
•
用
NSNumberFormatter
对象格式化数值。
•
用
NSDateFormatter
格式化日期
在
WatchKit
扩展里面,
NSLocale
对象返回配置在
Apple Watch
里面的本地化信息。用这个类获取当前用户的首选语言及其它语言还有其它本地化相关信息。
更多关于
App
国际化的内容请参考
Internationalization and Localization Guide
。
界面导航
对于那些不只一屏内容的
WatchKit App
来说,你必须选择一种在界面之间导航的方式。
WatchKit App
支持两种完全不一样的导航方式:
•
翻页模式
这种方式适合那些数据模型较简单的
App
,每页的内容和其它页面没有什么关联。翻页模式界面包含两个或更多的相互独立的视图控制器,但任何时候只有一个是可以
被显示的。
App
运行时,用户通过在屏幕上左右滑动来切换不同的界面。在屏幕下方有小点来指示用户当前页面所在的位置。
•
层级模式
这种方式适合数据模型较复杂或是数据结构有一定层级关系的
App
。层级模式的一般都是基于一个根视图控制器,在这个控制器里面你可以提供一个按钮,点击之后推
出一个新的视图控制器来显示在屏幕上。
尽管你不能在
App
里面混合使用两种导航方式,但你可以在层级模式里面使用模态视图。模态视图是一种打断用户正常浏览流程来要求用户输入或是展示信息的一种方式。在翻页模
式和层级模式中都可以使用模态视图。模态视图本身可以包含一个视图控制器或是包含多个基于翻页模式的控制器。
实现翻页模式界面
通过在
App
的
Storyboard
里面创建从一个视图控制器到下个视图控制器的
next-page
类型的
segue
来设置使用翻页模式。
在视图控制器之间创建
next-page segue
•
在
Storyboard
里面为你的每个页面添加视图控制器。
•
按住
Control
键点击
App
的主视图控制器不放,然后拖动到另一个视图控制器。
•
放开鼠标按键。
•
从
segue
类型面板选择
“next page”
类型。
•
用同样的方法在其它界面之间创建
segue
。你设置
segue
的顺序决定了界面上的显示顺序。
你在
Storyboard
里面定义的
segue
会在
App
启动的时候加载。你可以通过在程序启动的早期调用
reloadRootControllersWithNames:contexts:
方法来动态设置你要显示的页面集。比如你可
以在主视图控制器的
init
方法里面调用以上方法来强制
WatchKit
加载其它的视图集。
所有翻页模式的视图控制器都是在界面显示之前就被创建并初始化好的,但一次只能显示一个。一般来说,
Watchkit
显示初始化序列中的第一个视图控制器。如果要改变初始显示的页
面,在
init
或是
awakeWithContext:
方法中调用
becomeCurrentPage
方法。
用户从一个界面导航到另一个界面的同时,
WatchKit
负责激活、取消激活相应的视图控制器。在切换过程中,当前显示的视图控制器的
didDeactivate
方法会被调用,接着会调用下一
个将要显示的视图控制器的
willActivate
方法。通过视图控制器的
willActivate
方法来跟新显示最近的数据改变。
实现层级模式界面
在层级模式界面,你通过
segue
告诉
WatchKit
什么时候跳转到新的页面,或是调用当前视图控制器的
pushControllerWithName:context:
方法。在
Storyboard
中你从一个视图控制器上的
一个按钮,控件组,或是列表中的一行创建
push segue
到另一个视图控制器。如果你喜欢用编程的方式实现
push
,在任意视图控制器的
action
方法中调用
pushControllerWithName:context:
在
push
一个新的视图控制器到屏幕上的时候,建议通过
pushControllerWithName:context:
方法的
context
参数传入一个数据对象,通过这个对象可以新的视图控制器在显示之前
可以获取一些状态信息,同时通过这个对象告诉新的视图控制器哪些数据需要被显示。
被
push
出来的视图控制器会在屏幕的左上角有一个
“<”
标志来提醒用户可以导航回去。当用户点击屏幕左上角或是在屏幕上左滑,
WatchKit
会自动隐藏最上面的视图控制器。你也可
以通过调用
popController
方法来编程实现返回,但你不能使
App
的主视图控制器消失。
显示模态视图
模态界面通常是临时打断用户的正常浏览来提示或是显示信息。无论你
App
用的是什么导航方式,都可以在任何视图控制器上显示模态视图。要模态的展示一个视图控制器,可以使
用以下方法中的任意一个:
•
在
Storyboard
中创建
modal segue
。
•
调用
presentControllerWithName:context:
方法展示一个模态视图。
•
调用
presentControllerWithNames:contexts:
方法展示基于翻页模式布局的两个或两个以上的视图。
创建一个
modal segue
,连接到你想要显示的视图控制器。如果需要用
segue
显示多个视图,首先用
next-page segue
把需要模态展示的视图控制器连接在一起,这样你就把这些视图控
制器用翻页模式组织在一起了。再用
modal segue
连接到控制器组的第一个控制器上。如果
modal segue
连接到中间的某个控制器上,那么这个控制器之前的视图将不会显示。
模态视图的左上角显示了视图控制器的标题。当用户点击该标题时,
Watchkit
会让模态界面消失。因此最好设置有关闭模态界面提示意义的标题。例如,当显示信息的时候,可以设置
为
Done
或
Close
,如果没有为视图控制器设置标题,
WatchKit
默认显示
Cancel
界面对象
您通过界面对象操作你的
WatchKit app
的
UI
。界面对象是
WKInterfaceObject
类或者更明确的说是它的子类的实例。
WatchKit
框架为大部分(但不是全部)可视化元素提供了界面
对象,您可以在
storyboard
中添加到你的
UI
上的。界面对象不是视图。它们是与真实的视图进行无线通信的代理对象,用以实现
Apple Watch
上的
UI
。
>
注意
界面对象与
Apple Watch
上相对应的视图的通信是单向的,信息从
WatchKit
扩展传递到
Apple Watch
。换句话说,您可以设置一个界面对象的属性值但是不能获得属性的当前值。在对
设备状态进行改变的时候从
Apple Watch
上获取数据对性能和延迟均有影响。所以建议您在
WatchKit
扩展中保存界面的配置信息。
创建界面对象
通过在界面控制器中添加声明的属性并与
storyboard
文件中相对应的元素连接可以间接地创建界面对象。你不需要自己
alloc
或者
init
界面对象。在界面控制器对象初始化过程中,
WatchKit
自动为已连接的
outlet
创建界面对象。
当给界面对象添加属性的时候,在声明中设置合适的类的类型并且包含
IBOutlet
关键字。举个例子,一个标签(
label
)声明如下:
// SWIFT
class MySwiftInterfaceController {
@IBOutlet weak var label: WKInterfaceLabel!
}
// OBJECTIVE-C
@interface MyHelloWorldController()
@property (weak, nonatomic) IBOutlet WKInterfaceLabel* label;
@end
连接界面控制器中声明的属性与
storyboard
中相对应的项目。快速创建属性声明并与项目相连接的方法是利用
Xcode
中的辅助编辑器。显示辅助编辑器之后,按住
control
键从
storyboard
中的元素拖线到您的类定义的界面中来创建
outlet
。(在
Swift
中,拖线到您的类定义中。)定义了
outlet
的名字之后,
Xcode
在类中创建这个属性的声明并且与
storyboard
中的元素进行了连接。
在设计时配置界面
在设计的时候,用
Xcode
配置
storyboard
中可视化元素的外观。对于许多布局相关的属性,设计时间(
design-time
)是您唯一可以配置属性的机会。举个例子,您可以通过
WKInterfaceLabel
对象改变一个标签的文本、颜色和字体,但是不能改变行数或者每一行的行高。这些属性必须在
Xcode
中配置,如图
7-1
所示。
图
7-1
配置一个标签对象
图片
2.3
配置一个标签对象
关于更多如何配置界面对象的信息,请看在
WatchKit Framework Reference
中对应的类型描述。
运行时更改界面
在
WatchKit
扩展的代码中,您可以调用任何引用的界面对象的方法来更新应用程序的
UI
。界面控制器只有在活跃状态下可以改变界面对象的配置,这也包括初始化的时候。在
init
,
awakeWithContext:
以及
willActivate
方法中,调用方法给标签、图片和其他用户界面中的对象赋值。您也可以在界面控制器的动作方法中更新它们。
在初始化的时候,
WatchKit
在做其他事情之前先初始化界面控制器类这是很重要的。通过
WKInterfaceController
及其子类的初始化方法,
WatchKit
可以为应用程序创建界面对象。所以
您在界面控制器中写的任何初始化代码必须首先调用父类的实现。清单
7-1
显示了一个包含一个
outlet
(称为
label
)的
WKInterfaceLabel
对象的界面控制器的
init
方法。
清单
7-1
初始化界面一个控制器
// SWIFT
override init {
// Initialize variables here.
super.init
// It is now safe to access interface objects.
label.setText("Hello New World")
}
// OBJECTIVE-C
- (instancetype)init {
// Always call super first.
self = [super init];
if (self){
// It is now safe to access interface objects.
[self.label setText:@“Hello New World”];
}
return self;
}
为了提高性能和延长电池寿命,
WatchKit
框架优化了在应用程序界面对象上设置值的意图。在同一
Run Loop
循环中,不管你何时设置一个或多个界面对象的值,这些值都会被打包传
给
Apple Watch
并作为单个批处理以提高效率。合并这些属性意味着对象的给定的属性最后一次更改才能发给设备。更重要的是,如果给同样的属性设置了相同的值,那么会生成一条
日志信息,以便你跟踪重复调用。
关于您用来配置界面对象的方法信息,请看
WatchKit Framework Reference
中相对应的类说明。
响应用户交互
用按钮、开关已经其他的交互控件来改变应用程序状态。当点击按钮或者其他控件的值改变的时候,
WatchKit
会调用界面控制器中相关联的动作方法。每种类型界面对象对于它的动
作方法都有一个必须的格式,表
7-1
已经列出。可以改变动作方法的名称来匹配您的应用程序。
表
7-1
界面对象的动作方法
Object
Objective-C
Swift
Button
- (IBAction)buttonAction
@IBAction func buttonAction()
Switch
- (IBAction)switchAction:(BOOL)on
@IBAction func switchAction(value: Bool)
Slider
- (IBAction)sliderAction:(float)value
@IBAction func sliderAction(value: Float)
Menu Item
- (IBAction)menuItemAction
@IBAction func menuItemAction()
当界面包含
table
的时候,可以用
segue
或者界面控制器的
table:didSelectedRowAtIndex:
方法来响应点击表中一行。用
segue
显示另一个界面控制器。在执行
segue
之前,
WatchKit
调用
界面控制器的
contextForSegueWithIdentifier:inTable:rowIndex:
或者
contextsForSegueWithIdentifier:inTable:rowIndex:
方法当显示界面控制器的时候你可以指定上下文数据来用。如果你用
table:didSelectedRowAtIndex:
方法而不是
segue
,当点击行的时候,您可以执行任何动作。
当界面控制器初始化完成并且在屏幕上显示之后,只有用户与您的界面交互的时候,
WatchKit
才调用界面控制器的方法。如果在没有用户交互的情况下更新数据,你必须配置
NSTimer
对象,用它的处理器来执行任何需要的任务。
这些任务可能会耗费一到两秒的时间,可以考虑将其交给父级
iOS
应用来执行。长时间运行的任务比如网络连接和定位最好交给父级应用,然后通过共享组容器字典将信息传回给
WatchKit
扩展。关于将任务切换给父级应用的信息,请看
Communicating Directly With Your Containing iOS App
。
隐藏界面对象
通过隐藏对象可以让您用同一界面控制器显示不同类型的内容。每个
storyboard
文件中的场景必须包含所有在运行时需要显示其内容的界面对象。如果您基于可利用的数据自定义界
面,可以隐藏不需要的对象。隐藏一个对象可有效得将其从界面移除。在布局的时候,隐藏项目可以当做将其从布局中完全删除。隐藏对象,调用它的
setHidden:
方法并设置值为
YES
。
文本与标签
如需在
WatchKit
应用中显示一段文本,请使用标签对象。标签支持格式化文本,并且可以在运行时用代码改变文本内容。
拖动标签对象到对应的
storyboard
场景中便可添加标签对象。然后便可设置标签的初始化的文本以及格式。
WatchKit
同时支持标准字体和自定义字体。图
8-1
展示了标准字体风格的使
用。
**
图
8-1 **
使用标准字体风格的标签
图片
2.4
使用标准字体风格的标签
更多的设置标签的相关信息,请参照
WKInterfaceLabel
类参考
使用字体
WatchKit
应用,
glance
界面以及通知界面使用标准字体来显示文本。你应用中的
Controller
可以使用自定义字体来显示文本。
(glance
和通知界面无法使用自定义字体
)
为了让你的应用
使用自定义字体,你必须安装相应的字体,如下:
•
把你的自定义字体文件包含到
WatchKit
应用以及
WatchKit
扩展
Bundle
里。
•
给
WatchKit
应用的
Info.plist
文件添加
UIAppFonts
关键字并指向你添加的自定义字体。更多关于
UIAppFonts
关键字的相关信息,请参照
信息属性列表关键字参考
。
>
重要
为了能在运行时用自定义字体创建相应的字符串,你必须把自定义字体包含到你的
WatchKit
扩展中。
attributed string
发送到
Apple Watch
的时候,相应的字体信息也包含在其中。你
WatchKit
应用
bundle
中的自定义字体便可以对字符串进行渲染。
使用自定义字体来格式化文本时,需要创建一个包含字体信息的
attributed string
并把它设给标签,如代码
8-1
所示。字体名称和大小被编码到
attributed string
中
,
然后会被用来更新
Apple Watch
上的标签
.
如果定义的字体名称不符合系统字体或者你安装的自定义字体的名称,
WatchKit
会自动使用系统的字体。
代码
8-1
在标签中使用自定义字体
//
用自定义字体的信息设置
attributed string
let menloFont = UIFont(name: "Menlo", size: 12.0)!
var fontAttrs = [NSFontAttributeName : menloFont]
var attrString = NSAttributedString(string: "My Text", attributes: fontAttrs)
//
把文本设给标签对象
self.label.setAttributedText(attrString)
管理文件输入
WatchKit
为获取用户文本输入提供了一个标准的模式界面。界面允许用户通过语音或者选择标准短语以及表情等来进行输入。你可以通过调用当前处于激活状态的
Controller
的
presentTextInputControllerWithSuggestions:allowedInputMode:completion:
方法来显示输入界面
.
界面显示时,你可以指定输入类型并且可以使用一个
block
来处理结果。你也可以指定一个
或者多个初始化短语用来显示在界面上,如图
8-2
所示。用户可以从可用短语中选择或者输入其他短语。
图
8-2
收集用户的文本输入
图片
2.5
figure8-2
代码
8-2
展示了如何配置文本输入
Controller
并处理结果
.
在指定初始化短语和输入模式后,
Controller
以异步的方式加载。当用户选择了某一项或者取消了输入后,你的
block
会在主线
程中执行。使用
block
来获取用户选择的文本或者表情图片并且刷新你的应用。
代码
8-2
NSArray *initialPhrases = @[@"Ley's do lunch," @"Can we meet tomorrow?", @"When are you free?"];
[self presentTetxInputControllerWithSuggestions:initialPhrases allowedInputMode:WKTextInputModeAllwAnimatedEmoji completion:^(NSArray *results){
if(results && results.count > 0){
id aResult = [results objectAtInde:0];
//
使用字符串或者图片
}else{
//
用户没有选择任何东西
}
}];
```
文本多语言化
WatchKit
可以使用与
iOS
应用相同的方法来处理多语言环境。
*
在
storyboards
和
xib
文件中使用
Xcode
的多语言环境支持。多语言环境让你可以仅使用一个
storyboard
文件便能支持各种本地化语言。
storyboard
使用的本地化字符串储存在指定语言的
字符串文件中。
*
使用
NSLocalizedString
类的宏定义来动态获取本地化字符串。
*
使用
NSNumberFormatter
类可以通过用户的时区和场景设置来格式化数值。
*
使用
NSDateFormatter
类可以通过用户的时区和场景设置来格式化时间和日期。
对你的应用进行多语言化处理的时候
,
需要考虑的一个主要问题是安排好你的界面以使标签以及其他显示文本的控件有足够的显示空间。比如
,
当需要放置三个按钮控件的时候
,
纵向摆放会比横向摆放更妥当。
纵向摆放可以在文本变长的时候提供更多的空间给按钮。
更多关于应用的多语言化
,
请参照
多语言和本地化指南
图片
WatchKit
提供了下列方法把图片合并到内容
:
-
WKInterfaceImage
表示一个图像或图像序列。
-
WKInterfaceGroup
,
WKInterfaceButton
和
WKInterfaceController
类允许您指定一个图像作为其他内容的背景。
指定图像资产
当创建图像资产时请遵循以下建议
:
-
尽量使用
PNG
格式的图像。
-
请创建大小适当的图像。对于无法控制尺寸的图像
,
请使用
setWidth:
和
setHeight:
接口对象的方法
,
以确保图像以合适尺寸显示。
-
使用图像资产来管理图像。图像资产允许为各设备尺寸指定不同图像版本。
使用命名图像以提高性能
下列方法可以改变接口对象的当前图像
:
-
使用
setImageNamed:
或者
setBackgroundImageNamed:
方法来配置存于
WatchKit
应用程序包或设备缓存中的图像。
通过名称指定图片是首选方法
,
因为名称字符串会传输到
Apple Watch,
这样会花费更少的时间和能量。
WatchKit
会搜索
WatchKit
程序包找到指定名称的图像文件。如果未曾找到
,
就会搜索
device-
side
图像缓存以查找指定名称的图像。
-
使用
setImage:
,
setImageData:
,
setBackgroundImage:
或
setBackgroundImageData:
方法把图像数据从
WatchKit
扩展无线传输到
WatchKit
应用程序。
当在扩展中创建
UIImage
对象时
,
图像对象需保存在用户
iPhone
中
,
且使用前要发送给
Apple Watch
。使用
imageNamed:
方法从
WatchKit
扩展包而不是
WatchKit
应用程序来加载图像。如果
试图将该图像分配给接口对象
,
图像数据会通过无线传输到苹果手表。
缓存设备上的图像
对于在
WatchKit
扩展中创建的频繁使用图像
,
会在设备中根据名称缓存图像。在调用
WKInterfaceDevice
中的
addCachedImage:name:
或
addCachedImageWithData:name:
方法使用图像之前
需要进行图片缓存。
要使用接口中的缓存图片在你的界面
,
请执行以下操作
:
-
针对
WKInterfaceImage
对象
,
请调用
setImageNamed:
方法来指定缓存图片的名称。
-
针对
WKInterfaceGroup
和
WKInterfaceButton
对象
,
请调用
setBackgroundImageNamed:
方法来指定缓存图片的名称。
>
重要
当缓存动画图片时
,
使用
animatedImageWithImages:duration:
方法用所有的动画帧和缓存图片来创建一个单独的
UIImage
对象来。不要用单独地个性的帧来缓存图片。
Apple Watch
图像缓存尺寸受限
,
每个应用程序拥有大约
5 MB
的缓存空间。当应用程序占用缓存后
,
添加新图像之前就必须从缓存中移除现有图像。使用
removeCachedImageWithName:
方法来删除
单个图像或使用
removeAllCachedImages
方法来彻底清除缓存。
Tables
使用
tables
来显示整列动态改变的数据。
WatchKit
支持单列
Tables(
使用
WKInterfaceTable
类
)
。以表格的形式显示数据要求预先定义显示数据的布局并且在运行时把数据填充到表格中。具体来说
,
你需要在你的项目中做以下事情
:
-
在
storyboard
文件中
:
-
添加
table
对象到你的
Controller
场景中。给
table
对象创建一个输出口
(
outlet)
-
依照
配置你的行类型
中描述的方式来配置你表格中的行控制器
.
-
在代码中
:
-
定义一个行控制器类用以操作创建的表格的每一行
(
见
配置行类型
)
-
在初始化的时候添加行到表格
(
见
运行时配置表格内容
)
-
实现事件输入反馈
(
见
处理行选择
)
你可以给表格定义多种类型的行控制器
,
每一个都可以有不同的外观。你可以在运行时确定所需的行控制器类型以及他们排列的顺序。更多相关的信息
,
请参照
WKInterfaceTable
类参考
.
配置行控制器
行控制器是用来显示你表格内单一行数据的模板。每个表格需要一个或者多个行控制器。比如
,
你可以用不同的行控制器来显示表格主要内容
、
表格头
、
表格尾。当添加一个新的表格到场景中时。
Xcode
会自
动创建一个初始化的行控制制器
,
稍后你可以添加更多其他的行控制器
.
给表格添加行控制器
1.
在
Storyboard
中选中表格对象
.
2.
打开属性探测器
(Attributes inspector).
3.
用
Rows
属性来改变可用的行控制器的数量
.
每一个行控制器都有一些初始化元素。你可以把你需要的
,
比如标签
、
图片或者其他对象添加到行中。标签和图片的内容在设计的时候是无关紧要的。在运行时
,
你可以在对行进行配置的时候把内容替换掉。
每一个行控制器都由一个自定义类支持
,
你可以用这个类来接入行的内容。大部分行控制器都只包含与行的
UI
控件相关的属性
,
基本上是没有代码的。然而
,
当你给行添加按键或者其他可交互的控件时
,
你的行
控制器的相关类也可以包含对这些交互事件响应的相关方法。
给行控制器定义自定义类
1.
添加一个
Cocoa Touch
类到你的
WatchKit
扩展中
2.
让你新创建的类继承自
NSObject
。
3.
把运行时需要接入的属性
,
如标签
、
图片等添加到类中。确保这些属性使用以下的格式
,
保证属性的类型和对应的界面上的控件类型相同
:
@property (weak, nonatomic) IBOutlet WKInterfaceLabel *label; //Objective-C
以下是一个简单的行控制器类的定义
,
这个例子中
,
类包含了一个图片和一个标签的输入口。
SWITT class MainRowType: NSObject { @IBOutlet weak var rowDescription: WKInterfaceLabel! @IBOutlet weak var rowIcon: WKInterfaceImage! }
OBJECTIVE-C @interface MainRowType : NSObject @property (weak, nonatomic) IBOutlet WKInterfaceLabel* rowDescription; @property (weak, nonatomic) IBOutlet WKInterfaceImage*
rowIcon; @end
创建类并且连接输入口到对应控件上后
,
你的行控制器的配置就完成了。你必须给行分配一个标示性字符
,
以便在创建行时使用。
在
storyboard
中配置行控制器
1.
在
storyboard
中
,
选中行控制器对象。
2.
给行控制器设置一个唯一的标示性标签。稍后创建表格行的时候会用到标示。这个值必须确保在行类型中是唯一的
,
除此之外没有其他限制。在属性探测器中设置这个标示。
3.
把这个行控制器的类设成你的自定义类。并在
Identifty Inspector
中设置标示。
4.
创建并连接标签以及其他元素的输入口
,
运行时
,WatchKit
需要这些信息来创建行的界面对象。
图
10-1
展示了一个由代码
10-1
定义的标示为
mainRowType
,
类为
MainRowType
的行控制器。输入口
rowDescription
和
rowIcon
分别连接到行中的图片和标签对象。
图
10-1
检查
Xcode
中的行控制器
图片
2.6
figure10-1
运行时配置表格内容
运行时
,
你可以动态添加行到表格中
,
并且配置它的内容。
add and configure rows as part of your interface controller's initialization process.
创建并配置表格中的行
1.
基于你需要展示的数据来确定行的数量和类型
2.
使用
setRowTypes:
和
setNumberOfRows:withRowType:
方法来创建行。两个方法都可以在
WatchKit
扩展中创建行并且实例化行所对应的类。实例化后的类储存在表格中
,
可以通过
rowControllerAtIndex:
方法接入。
3.
使用
rowControllerAtIndex:
方法来对行进行迭代。
4.
使用行控制器对象来配置行的内容
setRowTypes:
和
setNumberOfRows:withRowType:
方法对对应的行控制器相关联的类进行实例化。调用这两个方法后
,
会立即获取最新创建的行控制器对象并用它来配置行。代码
10-2
展示了一个简单
的使用提供的数据对行的标签和图片进行配置的例子。数据由一个自定义数据类型
MyDataObject
组成的数组提供。
(
MyDataObject
类有一个字符串和一个图片属性
,
它的实现这边没有展示出来
)
行本则是
自定义类型
MainRowType
类的实例。
代码
10-2
创建并配置表格的各行
- (void) configureTableWithData:(NSArray *) dataObjects{ [self.table setNumberOfRows:[dataObjects count] withRowType:@"mainRowType"]; for(NSInteger i = 0; i < self.table.numberOfRows; i
++){ MainRowType *theRow = [self.table rowControllerAtIndex:i]; MyDataObject *dataObj = [dataObjects objectAtIndex:i]; [theRow.rowDescription setText:dataObj.text]; [theRow.rowIcon
setImage:dataObj.image]; } }
配置表格时
,
你可以限制初始化时行的数量来提高性能。由于表格的行都是必须在前台创建的
,
如果创建的数量过大会严重影响你应用的性能
.
具体的数量限制取决于你数据的复杂程度以及创建行需要的时间
,
建议把总数量限制在
20
以下。对于需要更多行的表格
,
可以考虑在初始化的时候只加载一部分行
,
并提供给用户可控制的展示更多行的方法。更好的解决方案是指显示最重要的那几行。比如
,
你的数据为定位数
据的时候
,
把数据限制到和用户当前位置相关的那几行。
处理行选择
界面控制器可以用来处理它所持有的任意表格的行选择事件。当用户点击表格上的某一行时
,
WatchKit
会选中那行并调用控制器的
table:didSelectRowAtIndex:
方法。使用这个方法来执行相关的行为。
比如
,
你可能需要展示一个新的界面控制器或者刷新行的内容。如果你不需要某一行处于可选状态
,
可以在
storyboard
中把对应的行控制器的
Selectable
选项取消。
上下文菜单
Apple Watch
上
Retina
屏的
Force Touch
提供了一种新的与内容交互的方式。与点击屏幕上的项目不同
,
该特性需要一定的压力才能激活与当前界面控制器相关的上下文菜单
(
如果有的话
)
。上下文菜
单是可选择的。您用上下文菜单显示与当前屏幕相关的操作。
WatchKit
在内容之上显示菜单
,
如图
11-1
。
图
11-1
一个包含三个项目的上下文菜单
上下文菜单可以显示多达
4
个动作
(
action
)
。每个动作由一个标题和一张图片表示。点击某个动作的图片会关闭菜单并执行相应的方法。点击屏幕上其他的地方只能关闭菜单。
设计菜单项
每个菜单项包含一个可点击区域和一个标题。可点击区域包括圆形背景
,
顶部是您所提供的图片。这张图片必须是模板图片
,
其
alpha
通道决定了绘制在背景顶部的形状。图片的不透明部分显示为黑色
,
全部
或者部分半透明可透出背景颜色。
您所提供的模板图片应当比它们所在的圆形背景要小一点。关于菜单图片的尺寸和创建图片指南的更多信息
,
请参考
Apple Watch Human Interface Guidelines
。
为界面控制器添加上下文菜单
您可以在设计时配置界面控制器的上下文菜单
,
但是也可以在运行时添加和移除菜单项。在设计时
,
编辑
storyboard
包括您想在指定的界面控制器上显示的菜单项。当之后初始化界面控制器的时候
,
您可以
添加菜单项来补充在
storyboard
中所创建的。通过代码创建的菜单项也可以删除。不管您是在
storyboard
中拖入菜单项还是通过代码添加
,
菜单中的菜单项不能超过
4
个。
在界面控制器中添加上下文菜单
1.
打开
storyboard
文件。
2.
从工具库
(
library
)
中拖拽一个菜单对象并添加到界面控制器场景中。
最初的菜单包含一个单独的菜单项。
3.
最多从工具库中拖拽
3
个菜单项到菜单中。
您也可以用菜单的属性检查器
(
Attributes inspector
)
来设置菜单项的数量。您所添加的菜单项不能通过编程删除。
4.
对于每一个菜单项
,
用属性检查器
(
Attributes inspector
)
指定菜单的标题和图片。两者都是需要的。
5.
在界面控制器类中将每个菜单项与操作方法连接起来。
菜单的操作
(
action
)
方法有以下格式
:
- (IBAction)doMenuItemAction
6.
保存
storyboard
文件。
想要在运行时添加菜单项
,
调用界面控制器对象的
addMenuItemWithImage:title:action:
或者
addMenuItemWithImageNamed:title:action:
方法。您指定的菜单项被附加到
storyboard
文件的菜单中。通过编程方式一直附属于菜单直到你明确移除它们或者界面控制器被销毁。
处理菜单项的点击
当用户点击菜单项时
,
WatchKit
关闭菜单并调用相关的动作方法。您可以在界面控制器中通过下面的语法来定义动作方法
:
// SWIFT @IBAction func doMenuAction() { // Handle menu action. }
// OBJECTIVE-C - (IBAction)doMenuItemAction { // Handle menu action. }
如果要求使用任何状态信息来执行操作
,
那您需要在界面控制器中存储并保持这些信息。举个例子来说
,
如果一个动作依赖于表的当前选中行
,
您的界面控制器必须包含一个变量来跟踪当前选中行。如果您需要
用户点击菜单动作之后的更多信息
,
那动作方法必须显示一个模态界面控制器。
设置
参数和设置是变动较少的数值
,
可以用于配置应用程序的行为或外观。如果
WatchKit
应用程序使用参数进行配置
,
就可以在工程中添加一个
WatchKit
专用设置包来显示这些设置。此设置包置于
iOS
应
用程序中
,
而设置本身会在用户手机上显示。
WatchKit
设置包与
iOS
设置工作包的工作流程相同。此设置包定义了系统控件和各控件修改的参数名称。用户手机的
Apple Watch
应用程序会获取设置包信息以便显示实际控件。当用户更改控件数值
时
,
系统会更新底层参数值。
如需获取设置包工作的详细信息
,
请参考
Preferences and Settings Programming Guide
。
创建
WatchKit
设置包
请按照以下操作向
Xcode
项目添加
WatchKit
设置包
:
1.
选择
File > New > File
。
2.
在
Apple Watch
选项中选择
WatchKit
设置包并单击
Next
。
3.
使用
Settings-Watch.bundle
名称来创建设置包
,
并添加到
iOS
应用程序中。命名
Settings-Watch.bundle
包是为了与
iOS
应用程序包进行区分。
WatchKit
设置包的初始内容与
iOS
应用程序设置包相同
,
详见清单
12-1
。
清单
12-1 WatchKit
设置包的内容
Settings-Watch.bundle/ Root.plist en.lproj/ Root.strings
关于如何配置设置包内容
,
请查看
Implementing an iOS Settings Bundle
。有关设置包的详细信息
,
请查看
Settings Application Schema Reference
。
允许访问
WatchKit
扩展的参数值
WatchKit
设置必须存储在共享组容器中
,
iOS
应用程序和
WatchKit
扩展均可对其进行访问。因为
WatchKit
设置包位于
iOS
应用程序
,
系统会默认把参数值写入
iOS
应用程序容器。如果想访问
WatchKit
扩展
,
您必须对项目执行以下配置
:
- App Group
同时支持
iOS
应用程序和
WatchKit
扩展。
选择相同的组标识符。
-
为
Root.plist
文件添加
ApplicationGroupContainerIdentifier
键。
当配置
App Group
功能时
,
把此键所对应索引设置为相同的标示符。
不需要把此键放入属性列表。
运行状态访问设置
要想访问存储于一组容器中的参数
,
请使用
initWithSuiteName:
方法来创建
NSUserDefaults
对象。调用此方法时
,
请指定组容器标示符所用的字符串。然后使用用户默认对象来访问参数值。下面提供
了访问自定义组的示例
:
清单
12-2
访问一个共享组容器的参数
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.example.MyWatchKitApp"]; BOOL enabled = [defaults boolForKey:@"enabled_preference"]; ```
如何访问参数的值,更多信息请参考
NSUserDefaults Class Reference
。
3
预览
预览概要
预览可以作为用户查看应用重要信息的辅助方法。并不是所有的应用都需要一个预览。预览可以及时提供一些相关的信息。例如,时钟应用的预览可以给用户展示下一次会议的时间,
而航空公司的应用可以给用户展示下次航班的登机信息。图
13-1
展示列表示例应用的预览,它显示了已经完成的项目条数和等待完成的项目条数。
图
13-1
列表示例应用的预览界面
图片
3.1
列表示例应用的预览界面
预览可以看作是手表插件应用和手表插件的扩展。你的预览界面存在于手表插件应用的
storyboard
文件中,界面是由自定义的
KInterfaceController
类来管理。然而,预览界面控制器的
唯一任务是设置预览界面的内容。预览不支持交互,且当触摸到预览界面时,会立即启动手表插件应用。
预览的生命周期
界面预览控制器和其他界面控制器的生命周期是相同的,除了一开始就初始化展现给用户的界面预览控制器。因为在初始化和展示预览之间只要一小点时间就可以完成,包含检查你的
willActivate
方法确保所展示的信息都是最新的。
更多关于的界面控制器的生命周期可以查看
WatchKit Extension Life Cycle
。
界面预览指导
Xcode
提供了固定的布局来排版你的预览内容。在选择一个布局来为内容使用之后,用下面的指导来填充内容:
•
设置预览来快速传达信息。
不要显示纯文本框。适当的使用一些图形,颜色和动画来传递信息。
•
聚焦于重要的信息数据。
预览不是手表插件应用的替代品。就像你的手表插件应用是
iOS
应用的缩小版应用一样,预览则是手表插件的缩小版
App
。
•
在预览界面里面不包含交互控件。
交互控件包含
buttons, switches, sliders, and menus
。
•
在预览界面中需要避免图表和地图。
然而却不是禁止,在狭小的空间里面使得地图和图表似乎没有什么作用。
•
及时查看信息显示。
用所有可用的资源,包含时间和位置来提供信息给用户。考虑到在预览界面初始化的时间和显示给用户的时间
之间会有一些变化,你需要记得更新你的预
览。
•
用系统的字体来展示所有的字体。
如果需要使用自定义的字体到你的预览,你需要渲染文本成为图像之后展示给用户。
因为一个应用只有一个预览控制器,所以一个控制器必须能够展示你需要展示的信息。
管理你的预览界面
当你添加手表插件应用到你的
Xcode
项目时,你可以指定是否想要预览界面。如果你忘记在建项目的时候添加预览界面,你也可以晚点再把它加到你的项目中。一个预览界面控制器
有轻微的不同显示方式在你的应用的
storyboard
上。尤其是,它有一个预览入口对象附属在上面,同时它有一个默认的布局,如下面的图
14-1
。
图
14-1
一个带有预览入口对象的界面控制器
图片
3.2
一个带有预览入口对象的界面控制器
你可以用自定义的
WKInterfaceController
的子类去配置运行时的预览内容。实现子类之后,你可以像实现其它手表插件应用中的界面控制器一样去实现它。
添加预览界面到你的应用
当为你的应用创建手表插件时,为了确保预览屏幕选项包含了创建的相关文件,你需要实现的预览界面。
Xcode
提供给你一个预览
storyboard
屏幕和一个自定义的预览界面控制器类。
如果你没有在创建的时勾选这个选项,你可以手动去配置。
手动创建预览界面
1.
在你的项目,创建一个
WKInterfaceController
的子类。创建这些新的资源文件并添加到你的手表插件扩展目标。给这个子类名一个恰当的名字。例如,
GlanceInterfaceController
。
2.
在你的
storyboard
文件中,拖拽
Glance Interface Controller
到你的
storyboard
。
这个屏幕展示你的新加入的预览界面控制器就会有一个预览入口对象附属在上面,就如图
14-1
所示。
3.
选择你
storyboard
上的预览界面控制器并打开
Identity inspector
。
4.
根据步骤
1
去设置你的预览界面控制器类。
手表插件应用有且只有一个预览界面。不要添加更多预览界面控制器到你的
storyboard
上。
实现一个预览界面控制器
实现预览界面控制器是相当简单的,因为只需要设置预览容器的标签和图像。所以你的预览通常只需要实现两个步骤。
•
使用
init
和
awakeWithContext:
方法去初始化你的预览界面并设置它的标签和图像的初始值。
•
根据最近的变化使用
willActivate
去更新预览界面。
使用一个
NSTimer
对象周期地变化更新它在屏幕上预览的内容。你无需更新
WKInterfaceDate
和
WKInterfaceTimer
对象,因为它们是自动更新的。
定制点击预览之后的启动方式
当用户触摸预览,苹果手表会启动相应的手机插件应用。通常,启动的应用之后会展示它的主界面控制器。如果需要定制点击预览之后的启动方式,按照如下步骤:
•
在预览界面控制器里:
•
配置预览界的通用方法
init
和
willActivate
。
•
调用
updateUserActivity:userInfo:webpageURL:
方法,并用
userInfo
属性去传递预览的状态信息给你的应用。在启动的时候,你的应用可以用上下文信息来展示不同的界面控
制器。
•
在你的主要界面控制器里:
•
实现
handleUserActivity
方法,用提供的
userInfo
字典去适当配置你的
UI
。
在启动的时候,调用
updateUserActivity:userInfo:webpageURL:
方法告诉手表插件调用主界面控制器的
handleUserActivity:
方法。用系统提供的的上下文数据适当地配置你的
UI
。例如,一个基于页面的界面应用,可以用这些提供的数据信息去选择初始化时展示哪一页。
4
通知
通知要点
如果你的
iOS
应用程序支持本地或者远程通知,
Apple Watch
会在合适的时候显示这些通知。当一个应用程序的本地或者远程通知被用户的
iPhone
收到后,
iOS
会决定是否将该通知显
示在
iPhone
或者
Apple Watch
上。对于发送到
Apple Watch
的通知,系统会隐约的告诉用户有一个通知了。如果用户选择查看通知,系统会先显示该通知的一个简短版本,之后才是一
个更详细的版本。用户可以选择忽略该通知,也可以启动你的
WatchKit
程序,或者通过通知上的有效活动按钮来触发其他操作。
应用程序不需要做任何事情来支持通知。系统提供了一个默认的通知显示界面来显示提醒信息,不过,应用程序也能自定义通知界面,包括自定义图形,内容和品牌。
>
注意:
只有在
iOS
支持它们的情况下,
Apple Watch
才能显示本地或者远程通知,有关如何支持本地和远程通知你的
iOS
应用程序信息,请查看
Local and Remote Notification Programming
Guide
。
Short-Look
界面
当用户第一次看到通知的时候,系统会显示一个
short-look
界面,图
15-1
展示的就是样子示例。
short-look
界面是非自定义并且不能滚动的。系统会使用一个模板来显示应用程序的名
字,图标以及存储在本地通知或者远程通知中得标题字符。如果用户继续查看通知,系统将会快速的从
short-look
界面转换到
long-look
界面。
图
15-1
一个
short-Look
界面
在
short-look
使用的标题字符串提供了该通知的一个简短的意图指示。对于本地通知,使用
UILocalNotification
对象的
alertTitle
属性指定该字符串。对于远程通知,则在负载数据
中的
dictionary
(字典)里添加一个
title
的
key
。获取更多关于添加一个标题字符串到你的通知中,请查看
Local and Remote Notification Programming Guide
Long-Look
界面
Long-look
界面是一个能滚动并且显示通知内容以及相关活动按钮的屏幕。如果你没有提供一个自定义的通知界面,
Apple Watch
会显示一个默认的界面,包含你应用程序的图标,通知
的标题以及提示消息。如果你提供了自定义的通知界面,
Apple Watch
则会显示你自定义的界面。
long-look
通知界面由三块区域组成:
•
sash
(腰带)区域是一个包含了应用程序图标和名称的浮层。
sash
区域在默认情况下是透明的,但是你也能在你自定义的通知界面修改它的颜色。
•
内容区域包含了通知的具体信息。对于自定义的界面,你可以配置该区域位于
sash
开始位置或者在它的下方。获取更多关于如何自定义内容区域,请查看
Custom Notification
。
•
按钮区域包含了
“
忽略
”
按钮以及其他
iOS
程序注册的活动按钮。
图
15-2
展示了一个包含了两个活动按钮的
long-look
通知示例。
图
15-2
一个
long-look
通知界面
图片
4.2
一个
long-look
通知界面
点击应用程序图标启动
WatchKit
程序。点击程序自定义的活动按钮则会将选择的活动发送到
iOS
应用程序或者你得
WatchKit
应用程序。前台活动被发送到你的
WatchKit
程序和拓展,
后台活动则发送到你的
iOS
程序。点击
“
忽略
”
按钮则啥都不做,直接关闭当前通知界面。点击其他地方则什么效果也没有。
更多关于如何为你的应用提供自定义
long-look
界面,请见
Custom Notification Interfaces
为通知添加活动按钮
活动按钮通过为通知提供封装响应为用户节省时间。
Apple Watch
借用
iOS
程序注册的交互通知来显示活动按钮,在
iOS 8
以及更高的版本中,应用都需要使用
UIUserNotificationSetting
对象来注册通知的类型。当注册信息的时候,应用程序同样可以注册一系列自定义通知目录,
Apple Watch
使用这些目录信息将对应的活动按钮添加到
long-
look
界面上。
代码
15-1
片段展示了如何为一个示例
iOS
程序注册设置和目录。这个方法是被包含
iOS
程序实现的,而不是
WatchKit
拓展,并且是在
iOS
程序启动时委托调用的。这个方法的是使用
swift
语言写的,还展示了
“invitation”
目录的创建和注册,
“invitation”
目录包含了接受和拒绝会议邀请的活动动作。
代码
15-1
在包含的
iOS app
中注册
Actions
func registerSettingsAndCategories() {
var categories = NSMutableSet()
var acceptAction = UIMutableUserNotificationAction()
acceptAction.title = NSLocalizedString("Accept", comment: "Accept invitation")
acceptAction.identifier = "accept"
acceptAction.activationMode = UIUserNotificationActivationMode.Background
acceptAction.authenticationRequired = false
var declineAction = UIMutableUserNotificationAction()
declineAction.title = NSLocalizedString("Decline", comment: "Decline invitation")
declineAction.identifier = "decline"
declineAction.activationMode = UIUserNotificationActivationMode.Background
declineAction.authenticationRequired = false
var inviteCategory = UIMutableUserNotificationCategory()
inviteCategory.setActions([acceptAction, declineAction],
forContext: UIUserNotificationActionContext.Default)
inviteCategory.identifier = "invitation"
categories.addObject(inviteCategory)
// Configure other actions and categories and add them to the set...
var settings = UIUserNotificationSettings(forTypes: (.Alert | .Badge | .Sound),
categories: categories)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
}
>
注意:
更多关于如何在你的
iOS
应用程序中配置目录和活动,请见
Local and Remote Notification Programming Guide
响应活动按钮点击
当用户点击活动按钮时,系统使用注册
UIUserNotification
对象中的消息来决定如何处理这个动作。动作能在前端和后台经过或者不经过验证被执行。不管怎样,前端和后台动作的处
理是不同的:
•
前端动作会启动你的
WatchKit
程序并且将你点击的按钮
ID
发送到你主控制接口中的
handleActionWithIdentifier:forRemoteNotification:
或者
handleActionWithIdentifier:forLocalNotification:
方法。
•
后台动作则会在后台启动能处理该动作的
iOS
程序,对应动作的信息将被发送到程序代理的
application:handleActionWithIdentifier:forRemoteNotification:completionHander
或者
application:handleActionWithIdentifier:forLocalNotification:completionHandler
方法。
对于前台按钮动作来说,
WKUserNotificationInterfaceController
子类并不处理这个按钮动作。选中一个前台按钮动作将启动你的应用,并为你应用的主入口点载入界面控制器。该初始
界面控制器负责处理所有按钮动作。这个界面控制器必须实现
handleActionWithIderntifier:forRemoteNotification
和
handleActionWithIdentifier:forLocalNotification
方法(如果适用的话)
来处理按钮动作。
管理自定义
Long Look
界面
自定义
long-look
通知界面包含两个独立部分,一个是静态的,一个是动态的。静态的界面是必须的,并简单的显示通知的提示信息,它的图片和文字是在设计的时候就配置的。动态
界面是可选的,只是为了让你有方法能自定义显示通知内容。
当你在
storyboard
中创建一个新的通知界面
controller
的时候,
Xcode
只会默认创建一个静态界面,如果你需要创建动态界面,需要在
storyboard
的通知目录对象中选择
“Has Dynamic
Interface”
属性。(只有在静态界面无法满足你需要的时,再选择添加动态界面才是明智的选择)。图
16-1
显示了
storyboard
文件中未修改的静态和动态界面场景。静态和动态场景都
是同一类型的相关通知,你可以使用通知
category
对象附加到静态场景来配置。
图
16-1
静态和动态的通知界面
图片
4.3
静态和动态的通知界面
当合法的通知类型被接受后,
WatchKit
会基于不同的因素来选择静态或者动态界面。当动态页面不存在,或者当电量不够,又或者你根本就没有明确告诉
WatchKit
显示动态界面的时
候,
WatchKit
会自动显示静态页面。在其他情况下,
WatchKit
会显示你的动态页面。在确定显示动态页面后,
WatchKit
会加载合适的
storyboard
资源然后准备合适的接口。就如图
16-
2
中所描述。
动态界面的加载过程就跟你应用程序中的界面
controller
一样,只是这个是通知界面
controller
特定的用来处理通知负载数据的。
图
16-2
准备通知界面
图片
4.4
准备通知界面
添加自定义通知界面到你的程序
当你为你的目标应用程序创建
WatchKit
程序时,你需要勾选上
Include Notification Scene
选项来创建对应通知接口的实现文件。
Xcode
提供了一个空的
storyboard
场景和一个用于你通
知接口
controller
的自定义子类。如果你在创建的时候没有选中刚才说的那个选项,而你又需要创建通知接口,则需要手动自己添加。
手动添加通知接口:拖一个通知接口
controller
对象到你的
storyboard
文件。新的接口仅仅只是包含了静态的页面控制器,为了创建动态接口,你必须执行以下配置步骤:
配置动态通知接口
controller
1.
在你的项目中,创建一个新的
WKUserNotificationInterfaceController
子类。
创建新的资源文件并将其添加到你的
WatchKit
拓展目标,然后给你的类一个合适的名字以区别于其他通知接口
controller
。
2.
勾选通知目录中得
Has Dynamic Interface
,这一步将添加动态场景到你的
storyboard
文件。
3.
设置你动态通知界面
controller
为在第一步创建的类。
应用程序可能有多个通知界面,你可以使用目录(
categories
)来区分。再你得
storyboard
文件中,使用
Notification Category
对象指定
category
名字来关联不同的场景。
WatchKit
使
用
category
值来决定在运行时加载哪个场景。如果进来的通知没有
category
,
WatchKit
则加载
category
名为
default
的。更多关于如何指定通知的
category
,请见
“
Configuring the
Category of a Custom Interface
”
。
配置自定义界面的
Category
每个通知接口必须有指定的通知
category
,这样才能告诉
Apple Watch
什么时候使用。发送进来的通知可以在负载数据中包含一个
category
键,值则你自己定义。
Apple Watch
使用
category
来决定显示哪个通知场景。如果进来的通知没有包含
category
字符串,
Apple Watch
显示配置时的默认通知界面。
指定你通知接口的通知类型,在你的
storyboard
中选择
“Notification Category”
对象并选择
Attributes
检查框,如图
16-3
所示。在检查框中得
Name
字段里输入
category
的名字。同时你
也能在这个框中设置你自定义界面的
sash
颜色和标题文字。
图
16-3
配置通知类型信息
图片
4.5
配置通知类型信息
当生成远程通知时,你的服务器通过在负载数据的
aps
字典里包含一个
category
键来指定通知类型。对于本地通知,你可以通过
UILocalNotification
对象的
category
属性的值
来指定。
>
注意
category
字符串同样也能定义哪些活动按钮(如果有的话)被追加到通知界面的最后,获取更多关于支持自定义活动的信息,请见
Adding Action Buttons to Notifications
。
配置静态通知界面
使用静态通知界面来定义一个简单的自定义的通知界面,静态界面的目的是为了在你
WatchKit
拓展的事件中提供一个回调接口,
WatchKit
拓展是无法及时配置动态界面的,以下是创
建一个静态界面的规则:
•
所欲的图像必须位于
WatchKit
应用程序包。
•
界面不能包含控件,表格,地图或者其他互动元素。
•
界面的
notificationAlertLabel
出口必须连接到一个
label
,这个
label
的内容设置为通知的提示信息。对于所有其他标签的文字都不要改变,而要再你的
storyboard
文件中指
定。
图
16-4
展示了在一个日历程序中自定义通知界面的静态和动态场景。通知箭头指向了静态场景,这个场景中包含了一个自定义
icon
和两个
label
。在静态界面中,
label
包含了一个字符
串
<message>
,它就是跟
notificationAlertLabel
出口相关的,因此它会在运行时收到通知的提示消息。
图
16-4
一个单一通知类型的静态和动态场景
图片
4.6
一个单一通知类型的静态和动态场景
配置动态通知界面
一个动态通知界面可以为用户提供更加丰富的体验。使用动态界面,你可以显示更多而不仅仅只是提示消息。你可以放置更多的信息,配置更多的
label
,显示动态生成的内容等等。
实现动态的通知界面需要创建一个
WKUserNotificationInterfaceController
的子类。当一个合适类型的通知过来时,这个子类的实现就是用来响应它的。
设计你的动态界面
配置你得动态界面就像其他界面
controller
场景,包括在你的子类中引用的
label
,
image
和其他场景中的对象。然后使用这些在运行时配置场景内容。点击通知页面启动应用程序,所
以通知界面不应该包含交互控制。
•
多为你的界面使用
label
,
image
,
group
和
separator
(分离器)。
•
你可以可以在你的界面中包含
table
和
map
。
•
不要包含
button
,
switch
或者其他交互控制。
在运行时配置你的动态界面
当一个合适类型的通知到达时,
WatchKit
从你的
storyboard
中选择合适的场景显示并告诉你的
WatchKit
拓展初始化对应
WKUserNotificationInterfaceController
子类。图
16-5
展示了
WatchKit
需要准备你界面的步骤,在初始化通知界面
controller
之后,
WatchKit
使用
didReceiveRemoteNotification:withCompletion:
或者
didReceiveLocalNotification:withCompletion:
方法
来发送有效负载数据,然后你使用负载数据来配置你通知界面的其他部分,然后调用设置完成处理程序块让
WatchKit
知道你的界面已经准备好了。
图
16-5
配置动态通知界面
图片
4.7
配置动态通知界面
总是使用
didReceiveRemoteNotification:withCompletion:
或者
didReceiveLocalNotification:withCompletion:
方法来配置你的通知界面,当实现了其中任意方法后,已经配置的界面提供的
处理程序会尽快执行完成。如果等得太久,
Apple Watch
会尝试放弃显示你的动态界面而以显示静态界面来代替。
清单
16-1
展示了
didReceiveRemoteNotification:withCompletion:
方法实现的示例。这个方法是通过一个虚构的日历程序,发送一个新的会议邀请远程通知。该方法从远程通知
的负载数据中提取数据并利用该数据来设置通知界面上的
label
值。为简单起见,该示例假定服务器总是为每个
key
都包含了一个合适的值。但你自己的代码应该做一些必要的错误检
查以保证这些负载数据是有效的。在配置完
label
之后,则调用处理程序让
WatchKit
知道自定义的界面以及准备好可以显示了。
清单
16-1
在一个远程通知里配置自定义界面
// Standard remote notification payload keys.
NSString* apsKeyString = @"aps";
NSString* titleKeyString = @"title";
// Payload keys that are specific to the app.
NSString* customDataKey = @"cal";
NSString* invitationDateKey = @"date";
NSString* invitationLocationKey = @"loc";
NSString* invitationNotesKey = @"note";
- (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void(^)(WKUserNotificationInterfaceType interface))
completionHandler {
// Get the aps dictionary from the payload.
NSDictionary* apsDict = [remoteNotification objectForKey:apsKeyString];
// Retrieve the title of the invitation.
NSString* titleString = [apsDict objectForKey:titleKeyString];
[self.titleLabel setText:titleString];
// Extract the date and time from the custom section of the payload.
// The date/time information is stored as the number of seconds since 1970.
NSDictionary* customDataDict = [remoteNotification objectForKey:customDataKey];
NSNumber* dateValue = [customDataDict objectForKey:invitationDateKey];
NSDate* inviteDate = [NSDate dateWithTimeIntervalSince1970:[dateValue doubleValue]];
// Format the date and time strings.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// Call a custom method to get the localized date format string for the user.
// The default date format string is "EEE, MMM d".
dateFormatter.dateFormat = [self dateFormatForCurrentUser];
NSString *formattedDateString = [dateFormatter stringFromDate:inviteDate];
// Call a custom method to get the localized time format string for the user.
// The default time format string is "h:mm a".
dateFormatter.dateFormat = [self timeFormatForCurrentUser];
NSString *formattedTimeString = [dateFormatter stringFromDate:inviteDate];
// Set the date and time in the corresponding labels.
[self.dateLabel setText:formattedDateString];
[self.timeLabel setText:formattedTimeString];
// Set the location of the meeting.
NSString* locationString = [customDataDict objectForKey:invitationLocationKey];
[self.locationLabel setText:locationString];
// Set the invitation's notes (if any).
NSString* notesString = [customDataDict objectForKey:invitationNotesKey];
[self.notesLabel setText:notesString];
// Tell WatchKit to display the custom interface.
completionHandler(WKUserNotificationInterfaceTypeCustom);
}
在调用完成处理代码块时,如果你希望
WatchKit
显示静态界面,那就指定
WKUserNotificationInterfaceTypeDefault
常量。
>
注意
通知界面的文字仅仅只支持系统指定的文字字体,如果你需要显示其他字体,最好是将文字嵌入图片中,然后显示那张图片。
测试你自定义界面
当你已经准备好在模拟器上测试你的动态界面时,为你的通知界面创建一个自定义运行计划,如果你还没有这么做的话。当你配置界面时,指定一个你希望发送到你的界面并包含测试
数据的
JSON
文件。
Xcode
会为指定的数据提供自定义的
JSON
文件。
更多关于设置运行计划并配置你的数据的信息,请见
The Build, Run, Debug Process
。
5
更新记录
2015-03-25
修改点
新建项目
贡献者
•
YouXianMing
•
vectxi
•
wangning
•
wanningliu
•
7heaven
•
staker
•
riverfeng
更多信息请访问
http://wiki.jikexueyuan.com/project/apple-watch-programming-guide/




