WatchKit App架构

在实现app的界面时,WatchKit app和WatchKit extension是串行工作的.当用户与Apple Watch上的app进行交互时,WatchKit app从故事版(storyboard)中选择合适的场景与之交互.例如,当用户查看app的glance的时候,它选择一个glance情景. 在选择这个情景之后,WatchKit 告知它配对的iPhone去启动WatchKit extension并且创建管理这个情景的对象.当情景完全配置好之后,它被展示到Apple Watch上. 信息在WatchKit app和WatchKit extension的传递是透明的.

图3-1 WatchKit app和WatchKit extension之间的交流

管理场景:界面控制器

每个场景被单个界面控制器对象管理,界面控制器对象是WKInterfaceController类的实例. 在WatchKit中的界面控制器和iOS中的view controller类似:它用于呈现和管理屏幕上的内容,并处理用户和内容的交互.不像view controller,interface controller不负责管理界面上的view. 这些View被WatchKit在情景背后管理.

WatchKit app典型的保护多个interface controller,每个负责展示不同类型的信息.因为每一个时刻只有一个界面控制器展示在屏幕上,app 展示新的界面控制器来响应用户的操作. App可以模态的呈现界面控制器. app导航的样式同样觉得了界面控制器如何被展现. 如何展现一个新的界面控制器,看这里

注意:Glance和自定义的通知界面使用不同于其他界面控制器的特定的界面控制器.关于glance的实现,可以看Galance Essentials 关于自定义通知界面的实现,可以看Notification Essentials

WatchKit App 的生命周期

用户与Apple Watch的交互驱使了app的启动和它的生命循环.使用者可以通过点击主屏幕启动,与glance交互启动,从定制的通知视图中启动. 这些交互中的每一个启动WatchKit app和与之相关的WatchKit extension. 你的WatchKit app和WatchKit 来来回回的传递数据,直到用户停止与你的app进行交互,这时候iOS 挂起extension 直到下一次交互到来.

在运行过程中,WatchKit 自动为当前的交互加载合适的场景. 如果用户查看app的glance,WatchKit从故事板中加载glance的场景;如果用户直接启动你的app,WatchKit为你的app加载初始化的场景. 随后,他加载场景,WatchKit 要求WatchKit extensions创建相关的界面控制器对象,这些对象用来准备展示给用户的场景. 图3.2展示了这个步骤. 你可以通过了解界面控制器如何工作的在[App Essentials]

图3.2 启动一个WatchKit app

使用界面控制器的init和awakeWithContext加载任何界面控制器展示需要的数据.不要使用willActivate初始化你的控制器. willActivate在你的控制器将要被展示到屏幕立即被调用,因此你可以在最后时刻做一些改变. 例如,你可能只有在整个控制器被展示在屏幕上时,做一些动画和其他的任务.

当界面控制完全展示到屏幕上时,用户可以通过控制器定制的行为方法去交互.当用户与列表,按钮,转换按钮,进度条,和其他控件进行交互时,WatchKit调用相关的行为方法与之交互.你使用这些交互方法来处理界面更新和其他相关的任务. 可以使用定时器(NSTimer)对象在你指定的时间去处理任务。

注意:Glance界面不支持事件方法. 点击你的Glance界面总是启动你的应用.

只有用户与你Apple Watch的app进行交互的时候,WatchKit extension才保持运行. 与Apple Watch的交互是简单的,因此界面控制器应该是轻量级的,并且不能跑耗时的任务. 当用户退出或者停止与你Apple watch交互,iOS不激活当前的界面控制器并且挂起你的extension,如图3-3

图3-3 界面控制器的生命周期

App生命周期不同阶段的任务

在app的不同阶段,iOS 通过调用WKInterfaceController对象的方法做回应.表3-1 列出了你需要在界面控制器中实现的关键方法,已经你需要在方法中干的任务.

Method

功能

init

你初始化界面控制器的第一次机会

awakeWithContext

这个方法让你通过可用的context data去配置界面控制器 用它来加载数据和更新故事板中的标签,图像,表格和其他控制器对象 context data是帮助生成新的控制器的数据 例如,在一个层级对象中push一个新的控制器对象,你可以指定传递给下一个层次的context data. 推荐但不强制 提供一个context data.

willActivate

这个方法告诉你你的界面马上要被用户看到. 使用这个方法可以对控制器做一些小的改变. 例如,你可以使用这个方法来更新标签上的数据. 更多的任务应该放到init和awakeWithContext方法中

didDeactivate

使用didDeactivate方法来清理你的界面控制器,使它返回到静止的状态. 例如,使用这个方法是定时器失效,停止动画.在这个方法中,你不能设置任何值. 这个方法被调用的时候,willActivate方法会被再次调用,任何视图对控制器的设置都会被忽略.

在模拟器中调试激活的代码

在测试期间,你可以锁定,解锁来验证你的激活和非激活代码是否如期望的那样. 当你使用硬件->锁定来锁定模拟器时,WatchKit 会调用当前控制器的didDeactivate方法. 当你随后调用解锁,WatchKit会调用willActivate方法.

与iOS app共享数据

如果你的iOS app和WatchKit extension依靠同样的数据,使用一个共享的文件夹来存放数据. app文件夹是一个多进程可以操作的安全容器. 因为你的WatchKit extension和iOS app运行与独立的沙盒环境,他们通常不会共享文件和互相交流.app文件夹可以让两个进程共享文件和用户的默认设置.

设置一个共享的文件夹在iOS app和WatchKit extension之间. 通过在target中添加一个entitlements 文件(必须的)和 在文件上添加com.apple.security.application-groups 来开启app文件夹. 为了共享数据,每个target必须选择相同的app文件夹.

在运行期间, 你通过在共享的目录下面读写这些文件来达到数据的共享. 使用NSFileManager的这个containerURLForSecurityApplicationGroupIdentifier方法来获取基地址来访问共享目录. 通过提供的URL迭代文件夹的内容,在目录中给文件创建新的URLs.

为了在app之间共享数据,基于共享目录创建一个NSUserDefaults的对象. 通过NSUserDefaults的initWithSuiteName:的方法创建对象,来访问共享的默认数据. 所以的操作都可以读或者写.

直接与包含它的iOS app交流

Apps与其包含它的应用合作紧密,可以通过openParentApplication:reply:这个方法发送对app发送接受请求. WatchKit extensions不支持后台执行模式;他们只在用户与Apple watch上的交换时才运行. 他们的container iOS app几乎没有限制,可以在后台运行,或者代表WatchKit extension收集信息. 活动完成可能需要花费额外的时间,例如获取用户的位置,这样应该让iOS app操作,再返回来与WatchKit extension交互.

当你调用openParentApplication:reply: 方法的时候,iOS在后台启动和唤醒containing iOS app,调用app 的application:handleWatchKitExtensionRequest:reply: 回调方法
这个回调使用提供的字典数据,发起请求,并给WatchKit extension一个回应.