您通過(guò)界面對(duì)象操作你的 WatchKit app 的 UI。界面對(duì)象是 WKInterfaceObject 類或者更明確的說(shuō)是它的子類的實(shí)例。WatchKit 框架為大部分(但不是全部)可視化元素提供了界面對(duì)象,您可以在 storyboard 中添加到你的 UI 上的。界面對(duì)象不是視圖。它們是與真實(shí)的視圖進(jìn)行無(wú)線通信的代理對(duì)象,用以實(shí)現(xiàn) Apple Watch 上的 UI。
注意
界面對(duì)象與 Apple Watch 上相對(duì)應(yīng)的視圖的通信是單向的,信息從 WatchKit 擴(kuò)展傳遞到 Apple Watch。換句話說(shuō),您可以設(shè)置一個(gè)界面對(duì)象的屬性值但是不能獲得屬性的當(dāng)前值。在對(duì)設(shè)備狀態(tài)進(jìn)行改變的時(shí)候從 Apple Watch 上獲取數(shù)據(jù)對(duì)性能和延遲均有影響。所以建議您在 WatchKit 擴(kuò)展中保存界面的配置信息。
通過(guò)在界面控制器中添加聲明的屬性并與 storyboard 文件中相對(duì)應(yīng)的元素連接可以間接地創(chuàng)建界面對(duì)象。你不需要自己 alloc 或者 init 界面對(duì)象。在界面控制器對(duì)象初始化過(guò)程中, WatchKit 自動(dòng)為已連接的 outlet 創(chuàng)建界面對(duì)象。
當(dāng)給界面對(duì)象添加屬性的時(shí)候,在聲明中設(shè)置合適的類的類型并且包含 IBOutlet 關(guān)鍵字。舉個(gè)例子,一個(gè)標(biāo)簽(label)聲明如下:
// SWIFT
class MySwiftInterfaceController {
@IBOutlet weak var label: WKInterfaceLabel!
}
// OBJECTIVE-C
@interface MyHelloWorldController()
@property (weak, nonatomic) IBOutlet WKInterfaceLabel* label;
@end
連接界面控制器中聲明的屬性與 storyboard 中相對(duì)應(yīng)的項(xiàng)目。快速創(chuàng)建屬性聲明并與項(xiàng)目相連接的方法是利用 Xcode 中的輔助編輯器。顯示輔助編輯器之后,按住 control 鍵從 storyboard 中的元素拖線到您的類定義的界面中來(lái)創(chuàng)建 outlet。(在 Swift 中,拖線到您的類定義中。)定義了 outlet 的名字之后,Xcode 在類中創(chuàng)建這個(gè)屬性的聲明并且與 storyboard 中的元素進(jìn)行了連接。
在設(shè)計(jì)的時(shí)候,用 Xcode 配置 storyboard 中可視化元素的外觀。對(duì)于許多布局相關(guān)的屬性,設(shè)計(jì)時(shí)間(design-time)是您唯一可以配置屬性的機(jī)會(huì)。舉個(gè)例子,您可以通過(guò) WKInterfaceLabel 對(duì)象改變一個(gè)標(biāo)簽的文本、顏色和字體,但是不能改變行數(shù)或者每一行的行高。這些屬性必須在 Xcode 中配置,如圖 7-1 所示。
圖 7-1 配置一個(gè)標(biāo)簽對(duì)象
http://wiki.jikexueyuan.com/project/apple-watch-programming-guide/images/formatted_text_attributes_2x.png" alt="配置一個(gè)標(biāo)簽對(duì)象" />
關(guān)于更多如何配置界面對(duì)象的信息,請(qǐng)看在 WatchKit Framework Reference 中對(duì)應(yīng)的類型描述。
在 WatchKit 擴(kuò)展的代碼中,您可以調(diào)用任何引用的界面對(duì)象的方法來(lái)更新應(yīng)用程序的 UI。界面控制器只有在活躍狀態(tài)下可以改變界面對(duì)象的配置,這也包括初始化的時(shí)候。在 init,awakeWithContext: 以及 willActivate 方法中,調(diào)用方法給標(biāo)簽、圖片和其他用戶界面中的對(duì)象賦值。您也可以在界面控制器的動(dòng)作方法中更新它們。
在初始化的時(shí)候,WatchKit 在做其他事情之前先初始化界面控制器類這是很重要的。通過(guò) WKInterfaceController 及其子類的初始化方法,WatchKit 可以為應(yīng)用程序創(chuàng)建界面對(duì)象。所以您在界面控制器中寫(xiě)的任何初始化代碼必須首先調(diào)用父類的實(shí)現(xiàn)。清單 7-1 顯示了一個(gè)包含一個(gè) outlet(稱為 label)的 WKInterfaceLabel 對(duì)象的界面控制器的 init 方法。
清單 7-1 初始化界面一個(gè)控制器
// 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;
}
為了提高性能和延長(zhǎng)電池壽命,WatchKit 框架優(yōu)化了在應(yīng)用程序界面對(duì)象上設(shè)置值的意圖。在同一 Run Loop 循環(huán)中,不管你何時(shí)設(shè)置一個(gè)或多個(gè)界面對(duì)象的值,這些值都會(huì)被打包傳給 Apple Watch 并作為單個(gè)批處理以提高效率。合并這些屬性意味著對(duì)象的給定的屬性最后一次更改才能發(fā)給設(shè)備。更重要的是,如果給同樣的屬性設(shè)置了相同的值,那么會(huì)生成一條日志信息,以便你跟蹤重復(fù)調(diào)用。
關(guān)于您用來(lái)配置界面對(duì)象的方法信息,請(qǐng)看 WatchKit Framework Reference 中相對(duì)應(yīng)的類說(shuō)明。
用按鈕、開(kāi)關(guān)已經(jīng)其他的交互控件來(lái)改變應(yīng)用程序狀態(tài)。當(dāng)點(diǎn)擊按鈕或者其他控件的值改變的時(shí)候,WatchKit 會(huì)調(diào)用界面控制器中相關(guān)聯(lián)的動(dòng)作方法。每種類型界面對(duì)象對(duì)于它的動(dòng)作方法都有一個(gè)必須的格式,表 7-1 已經(jīng)列出??梢愿淖儎?dòng)作方法的名稱來(lái)匹配您的應(yīng)用程序。
表 7-1 界面對(duì)象的動(dòng)作方法
| 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() |
當(dāng)界面包含 table 的時(shí)候,可以用 segue 或者界面控制器的 table:didSelectedRowAtIndex: 方法來(lái)響應(yīng)點(diǎn)擊表中一行。用 segue 顯示另一個(gè)界面控制器。在執(zhí)行 segue 之前,WatchKit 調(diào)用界面控制器的 contextForSegueWithIdentifier:inTable:rowIndex: 或者 contextsForSegueWithIdentifier:inTable:rowIndex: 方法當(dāng)顯示界面控制器的時(shí)候你可以指定上下文數(shù)據(jù)來(lái)用。如果你用 table:didSelectedRowAtIndex: 方法而不是 segue,當(dāng)點(diǎn)擊行的時(shí)候,您可以執(zhí)行任何動(dòng)作。
當(dāng)界面控制器初始化完成并且在屏幕上顯示之后,只有用戶與您的界面交互的時(shí)候,WatchKit 才調(diào)用界面控制器的方法。如果在沒(méi)有用戶交互的情況下更新數(shù)據(jù),你必須配置 NSTimer 對(duì)象,用它的處理器來(lái)執(zhí)行任何需要的任務(wù)。
這些任務(wù)可能會(huì)耗費(fèi)一到兩秒的時(shí)間,可以考慮將其交給父級(jí) iOS 應(yīng)用來(lái)執(zhí)行。長(zhǎng)時(shí)間運(yùn)行的任務(wù)比如網(wǎng)絡(luò)連接和定位最好交給父級(jí)應(yīng)用,然后通過(guò)共享組容器字典將信息傳回給WatchKit擴(kuò)展。關(guān)于將任務(wù)切換給父級(jí)應(yīng)用的信息,請(qǐng)看 Communicating Directly With Your Containing iOS App。
通過(guò)隱藏對(duì)象可以讓您用同一界面控制器顯示不同類型的內(nèi)容。每個(gè) storyboard 文件中的場(chǎng)景必須包含所有在運(yùn)行時(shí)需要顯示其內(nèi)容的界面對(duì)象。如果您基于可利用的數(shù)據(jù)自定義界面,可以隱藏不需要的對(duì)象。隱藏一個(gè)對(duì)象可有效得將其從界面移除。在布局的時(shí)候,隱藏項(xiàng)目可以當(dāng)做將其從布局中完全刪除。隱藏對(duì)象,調(diào)用它的 setHidden: 方法并設(shè)置值為 YES。