界面对象
您通过界面对象操作你的 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 配置一个标签对象
关于更多如何配置界面对象的信息,请看在 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
。