寫了一個測試的demo 發現若是設置了next Page,在InterfaceController中的push操做是不成功的(點擊第一個"助力"的row push到TowInterfaceControl) 可是present是好用的html
參考轉載:http://www.swiftkiller.com/?p=613ios
A.概覽編程
一.概覽--開始爲 Apple Watch 進行開發json
-1.第三方應用須要兩個不一樣的可執行文件:在Apple Watch上運行的Watch應用(Watch應用只包含與應用程序的用戶界面有關的storyboards和資源文件),swift
在用戶iPhone上運行的WatchKit應用擴展(WatchKit應用擴展則包含了用於管理、監聽應用程序的用戶界面以及響應用戶交互的代碼)。緩存
Watch應用須要儘量實現Apple Watch提供的全部交互動做。因爲Watch應用目的在於擴展iOS應用的功能,所以Watch應用和WatchKit應用擴展將被捆綁在一塊兒,而且都 會被打包進iOS應用包。若是用戶有與iOS設備配對的Apple Watch,那麼隨着iOS應用的安裝,系統將會提示用戶安裝相應的Watch應用。服務器
-2.建立網絡
1.建立Watch應用 app
2.建立Glance界面框架
3.自定義通知界面
要向現有項目中添加Watch應用對象,請執行如下操做:
1. 打開現有的iOS應用項目
2. 選擇 File > New > Target,而後選中Apple Watch
3. 選擇 Watch App
4. 單擊 Next
5. 若是您想要使用glance或者自定義通知界面,請選擇相應的選項
咱們建議您激活應用通知選項。選中以後就會建立一個新的文件來調試該通知界面。若是您沒有選擇這個選項,那麼以後您只能手動建立這個文件了。
6. 單擊 Finish
若是修改了bundleId,那麼相對應的Watch應用和WatchKit應用擴展的bundleId圖3-2 啓動Watch應用
當用戶在Apple Watch上與應用進行交互時,WatchKit應用擴展將保持運行。若是用戶明確退出應用或者中止與Apple Watch進行交互,那麼iOS將停用當前界面控制器,並暫停應用擴展的運行,如圖3-3所示。與Apple Watch的互動是很是短暫的,所以這幾個步驟都有可能在數秒之間發生。因此,界面控制器應當儘量簡單,而且不要運行長時任務。重點應當放在讀取和顯示 用戶想要的信息上來。
圖3-3 界面控制器的生命週期
應用生命週期中各階段需執行不一樣的任務
在應用生命週期的不一樣階段,iOS將會調用WKInterfaceController對象的相關方法來讓您作出相應的操做。表3-1列出了大部分您應當在界面控制器中聲明的主要方法。
Table 3-1:WKInterfaceController`的主要方法
方法 | 要執行的任務 |
initWithContext: | 這個方法用來準備顯示界面。藉助它來加載數據,以及更新標籤、圖像和其餘在故事板場景上的界面對象。 |
willActivate | 這個方法可讓您知道該界面是否對用戶可視。藉助它來更新界面對象,以及完成相應的任務,完成任務只能在界面可視時使用。 |
didDeactivate | 使用didDeactivate方法來執行全部的清理任務。例如,使用此方法來廢止計時器、中止動畫或者中止視頻流內容的傳輸。您不能在這個方法中設置界面控制器對象的值,在本方法被調用以後到willActivate方法再次被調用以前,任何更改界面對象的企圖都是被忽略的。 |
除 了在表3-1中列出的方法,WatchKit一樣也調用了界面控制器的自定義動做方法來響應用戶操做。您能夠基於用戶界面來定義這些動做方法。例如,你可 能會使用動做方法來響應單擊按鈕、跟蹤開關或滑條值的變化,或者響應表視圖中單元格的選擇。對於表視圖來講,您一樣也能夠用table:didSelectRowAtIndex:而不是動做方法來跟蹤單元格的選擇。用好這些動做方法來執行任務並更新Watch應用的用戶界面。
提示:Glances不支持動做方法。單擊應用glance始終會啓動應用。
與Containing iOS應用共享數據
如 果您的iOS應用和WatchKit應用擴展都依賴於相同的數據,那麼您可使用共享程序組來存儲數據。共享程序組是一個位於本地文件系統的區域,應用擴 展和應用都可以訪問。因爲兩個程序在不一樣的沙箱環境中運行,它們通常狀況下都不與對方共享文件和進行通訊。共享程序組讓共享數據成爲可能。你可使用這個 空間來存儲共享的數據文件或者在兩個程序間交換消息。
您能夠在iOS應用和WatchKit應用擴展中的Capabilities選項卡中 啓動共享程序組。激活這項功能後,Xcode將會爲每一個對象添加受權文件(須要的話),並給那個文件添加 com.apple.security.application-groups受權。要共享數據,這兩個對象必須選擇相同的共享程序組。
程序運行時,您能夠經過在共享容器目錄中讀寫文件以在兩個程序間共享數據。要訪問容器,請使用NSFileManager中的containerURLForSecurityApplicationGroupIdentifier:方法來接收該目錄的根路徑。使用方法返回的URL來枚舉目錄內容或者在目錄中爲文件建立新的URL。
重要:請始終在共享容器目錄中使用文件演示器和協調器來訪問文件。文件演示器和協調器容許對文件和目錄進行同步訪問。沒有它們,您的WatchKit應用擴展和iOS程序可能會相互衝突並毀壞共享的文件。有關如何使用文件演示器和協調器的信息,請參閱:File System Programming Guide。
四.概覽--使用iOS技術
· 避免使用須要用戶權限的技術,好比Core Location。
· 不要使用後臺執行模式的技術。
· 避免使用須要長時間運行的技術。
要使用iOS技術,其中一種解決方法是讓您的iOS應用來使用這些技術。例如,在您的iOS應用中使用位置服務,而不是在WatchKit中使用這個技術。iOS應用能夠收集所需的數據而後經過共享程序組來讓應用擴展稍後訪問。
當 使用iOS技術的時候,請始終確保使用這些技術可以給用戶帶來明顯的好處,而且不要讓這些技術成爲您應用的核心功能。一樣要記住某些技術須要您提供用法說 明,使用說明存放在`Info.plist`文件中,其描述了您打算如何使用相應的數據。若是在iOS應用中已經有了這些用法說明字符串,請考慮更新它們 以讓用戶明白,這些數據可能會結合Watch應用來使用。
B.WatchKit Apps
一.WatchKit Apps--App概要
-1.在Xcode中建立你的界面時,儘量地讓對象本身調整尺寸來適應可用空間。App界面應該能夠運行兩種尺寸的Apple Watch。讓系統調整對象尺寸來適應可用空間,這樣可最小化爲每款設備編寫的代碼量。
-2.在運行時更新界面(Updating Your Interface at Runtime)
在運行過程當中,界面控制器能讓對象在相應的storyboad場景中作以下改變:
設置或修改數據變量
支持改變對象的外觀
改變對象的尺寸
改變對象的透明度
顯示或隱藏對象
你不能添加新的對象到界面或者改變已經存在對象的次序。儘管你不能移除對象,但你能夠經過隱藏對象來暫時從圖層中移除。當控件被隱藏時,其餘對象將會填充此前被佔用的空間。 若是不想填滿這些空間,能夠把對象的alpha值設置爲0。
二.WatchKit Apps--界面導航
對於內容超過一屏的WatchKit app來講,您必須在設計時選擇一個導航類型。您所選擇的導航類型定義瞭如何在應用程序中展現和管理界面控制器。WatchKit支持兩種互斥的界面風格:
分層風格
分頁風格
這兩種導航均可以模態形式展現一個或多個界面。當您想暫時打斷用戶的工做流程以請求輸入或者展現信息時,適合使用模態形式。當模態地展現兩個或多個界面控制器時,系統會以一系列的頁面展現它們,相似於基於分頁的導航。
-1.實現分層界面(Implementing a Hierarchical Interface)
分層界面主要針對分層的數據集,用戶可在此選擇某個條目以展現相關詳細信息。分層界面一般始於單個的根界面控制器。在該界面控制器中,您能夠經過調用當前界面控制器的pushControllerWithName:context:方法在屏幕上推出一個新的界面控制器。一般,當用戶點擊按鈕或表格行時,您能夠從動做方法中調用該方法。每一個新的界面控制器可展現下一級分層中的信息。
當 在屏幕上推出新的界面控制器時,會將數據對象傳遞給pushControllerWithName:context:方法的上下文參數。在新界面控制器展 示在屏幕上以前,這個上下文對象就是您與其通訊的機會。您可使用該對象來告知界面控制器展現什麼樣的數據或者傳達什麼樣的狀態信息。
想要解除界面控制器,可調用其popController方法。用戶也能夠直接從屏幕的左邊緣輕掃解除界面控制器。界面控制器解除後即失效,而先前的界面控制器將會從新展現。根界面控制器不能被解除。
-2.實現基於分頁的界面(Implementing a Page-Based Interface)
基於分頁的界面主要針對本質上沒有分層的數據。分頁界面包含兩個或者多個獨立的界面控制器,而且在指定時間內僅展現其中一個界面。在運行時,經過向左/右輕掃屏幕進行導航。屏幕底部的圓點指示器控件指示用戶當前的位置。
在設計過程當中,您能夠建立下一頁的segue,以便在app的storyboard文件中配置分頁界面。想要建立該segue:
1.對您但願做爲第一屏的界面控制器執行Control-click操做,並將其拖拽到不一樣的界面控制器中。
應該強調第二個界面控制器,以指明segue是可用的。
2.釋放鼠標按鈕。
3.從relationship segue面板中選擇next page。
一般在storyboard文件中配置一組初始的頁面集合。當app啓動時,WatchKit會實例化和初始化您的初始界面控制器,而後是分頁界面中的其餘 界面控制器。若是您想改變一組界面控制器,請在初始界面控制器的init方法中調用 reloadRootControllersWithNames:contexts:方法。調用該方法會使得WatchKit在嘗試展現界面中任何其餘頁 面以前加載新的界面控制器。您也能夠在app運行時調用reloadRootControllersWithNames:contexts:方法來改變展 示中的頁面集合。
當系統加載您的WatchKit app界面時,它將實例化和初始化組成界面的全部界面控制器。當用戶從一個界面控制器切換至下一個時,它將調用當前界面控制器的didDeactivate方法,以及即將展現的界面控制器的willActivate方法。willActivate方法可確保界面中的信息是最新的。
-3.以模態形式展現界面控制器(Presenting Interface Controllers Modally)
模態界面可臨時中斷當前導航流以提示用戶或者展現信息。您可使用分頁界面或分層界面來組成一個模態界面。想要模態地展現界面控制器,請從當前可視界面中調用如下方法之一:
調用presentControllerWithName:context:方法來模態地展現單個界面控制器。
調用presentControllerWithNames:contexts:方法展現兩個或者多個使用分頁佈局的界面控制器。
模態界面的左上角包含一個文本標籤,當點擊時會解除界面。若是您沒有爲該標籤指定一個準確的字符串,那麼WatchKit會自動爲其使用"Cancel"。 您能夠根據須要更改字符串,以反映解除模態視圖的真實用意。好比,當展現那些您不但願用戶響應的內容時,您可能會將字符串更改成"Done"或 "Close"。若是您使用了"Cancel"字符串,那要考慮爲接受模態界面中的任何更改添加一個或多個按鈕。
三.Interface Object--界面對象
Apple Watch上界面對象與對應的視圖之間的通訊有單向性,即信息流是從WatchKit擴展傳到Apple Watch的。換句話說,你能夠對界面對象的某些屬性值進行更改設置,但你沒法得到其屬性的當前值。在對設備狀態進行更改的時候從Apple Watch上獲取數據對性能和延遲均有影響。所以咱們推薦你在本身的WatchKit擴展中保存你對界面的配置信息。
-1.在設計階段配置界面
在設計階段,可使用Xcode配置Storyboard中視覺元素的外觀。對於不少與佈局相關的屬性,design-time是您能夠配置屬性的惟一機會了。好比,你可使用一個WKInterfaceLabel對象來更改標籤的文本、顏色以及字體,不過卻不能更改它的行數或者是行高。這些屬性必須在Xcode中配置,以下圖:
瞭解更多有關如何配置界面對象的信息,可參考WatchKit框架介紹中相關的類型描述。
-2.在運行時更改界面
爲了提升性能和延長電池壽命,WatchKit框架優化了在app界面對象上設置數值的任何試圖。只要在同一的Run Loop中,不管你什麼時候爲一個或者多個界面對象設置值,這些值都會被打包傳給Apple Watch並做爲單個批處理以提升效率。合併這些改變意味着對象的既有屬性只有最後一次更改被髮送給設備。更爲重要的是,若是爲一樣的屬性設置了相同的 值,那麼會生一條日誌信息,以便你跟蹤重複調用。
-3.響應用戶交互
請使用按鈕、開關以及其餘的交互控件來更改應用狀態。當點擊按鈕或某一控件的值發生 變化時,WatchKit會調用界面控制器中相關的動做方法(action method)。每種界面對象針對其動做方法都有一個必須的格式,以下圖所示,能夠更改動做方法的名稱以匹配您的應用程序:
當您的界面控制器初始化並顯示出來以後,WatchKit就能夠調用它的動做方法了,固然僅在用戶與相應的控件交互時。若是您但願在沒有用戶交互的狀況下更新用戶界面,那必須配置一個NSTimer對象來安排這個任務。
這 些任務可能會耗費一到兩秒的時間,能夠考慮將其交由父級應用(parent iOS app)來執行。像網絡鏈接以及定位這些須要較長運行時間的任務最好由父級應用執行,而後經過一個共享的羣組容器目錄將信息傳回WatchKit擴展。關 於將任務切換給parent app來執行的更多信息,請參看Communicating Directly with Your Containing iOS App.
經過隱藏對象你可使用相同的界面控制器來顯示不一樣類型的內容。 Storyboard文件中的每一個場景都必須包含全部運行時須要展現其內容的界面對象。若是你要根據有效數據來自定義界面,那能夠將不須要的對象隱藏起 來。隱藏一個對象可有效地將其從界面中移除。在設計佈局時,隱藏起某些項目就能夠當作是將其從佈局中徹底刪除。若是要隱藏某個對象,只須要調用setHidden:方法併爲其傳遞YES值就好了。
四.Watch Apps--文本、標籤以及圖片
-1.Using Custom Fonts 使用自定義字體
除了標準字體風格,你能夠定製通過格式化的字符串的字體。按照下面的方式來定製字體:
· 在Watch app和WatchKit擴展包中都導入定製的字體文件。
· 添加__UIAppFonts__鍵到你的Watch app中的Info.plist文件中,並用這個來指定添加到包中的字體。更多關於此鍵的信息,請查閱 Information Property List Key Reference
注意:你必須在WatchKit擴展中導入字體,才能在運行時建立指定字體的字符串。當發送到Apple Watch的時候,字體的信息包含了屬性字符串,在Watch app包中的字體拷貝將會渲染這個字體。
使用自定義的字體做爲標籤的字符串
// Configure an attributed string with custom font information. UIFont* menloFont = [UIFont fontWithName:@"Menlo" size:12.0]; NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"My Formatted Text" attributes:@{NSFontAttributeName: menloFont}]; // Set the text on the label object. [self.myCustomFontLabel setAttributedText:attrString];
-2.Customizing the System Font 自定義系統字體
自定義系統字體,使用UIFontDescriptor對 象來指定基於系統的新字體。列表 8-2 的例子展現了怎樣讓定製只使用小寫字符的標準的系統字體。在轉換系統字體到一個字體描述符後, 添加__kLowerCaseType__和__kLowerCaseSmallCapsSelector__屬性(在Core Text framework中定義)而後字體描述符的結果來建立新的字體對象。
指定系統字體爲小寫
CGFloat fontSize = 18.0; UIFont *afont = [UIFont systemFontOfSize:fontSize]; UIFontDescriptor *fontDescriptor = [[afont fontDescriptor] fontDescriptorByAddingAttributes:@{ UIFontDescriptorFeatureSettingsAttribute : @[ @{ UIFontFeatureTypeIdentifierKey : @(kLowerCaseType), UIFontFeatureSelectorIdentifierKey : @(kLowerCaseSmallCapsSelector) },], }]; UIFont *smallCapFont = [UIFont fontWithDescriptor:fontDescriptor size:fontSize];
-3.國際化您的文本代碼
Watch apps能使用iOS apps想通的國際化技術方法。
· 使用基於Xcode國際化支持的storyboard和xib文件。基於國際化可讓你僅僅只用一個storyboad文件就能支持全部的本地化。本地化字符串分別存在特定的區域語言字符串中。
· 使用NSLocalizedString族的宏定義來讓程序自動檢索本地化字符串。
· 經過NSNumberFormatter類使用用戶所在區域和本地的設置來格式化數值型的值。
· 經過NSDateFormatter類使用用戶所在區域和本地設置來格式化時間。
當要國際化你的應用,你主要考慮的是如何調整界面,讓標籤列表(還有其餘文本的控制)可以足夠容納得下。好比,比起水平的排列三個按鈕,垂直排列更好能給每個標籤的文本提供更長的容納空間。
更多關於國際化的信息,請查閱Internationalization and Localization Guide。
-4.圖像
· WKInterfaceImage用於展現單個的圖片或者一組圖片做爲單個圖像展現的內容。
· WKInterfaceGroup、WKInterfaceButton和WKInterfaceController類容許你指定一張圖做爲某些內容的背景圖。
指定你的圖像資源
下面是當你建立圖像資源時要注意的準則:
· 儘可能只用PNG的格式的圖。
· 保證建立的圖像的尺寸是符合你的界面的。對於你很差控制的圖像,使用setWidth:和setHeight:方法來作自適應。
使用命名的圖片來提升執行效率
下面是幾種更換界面對象現有圖片的方式:
· 使用 setImageNamed: 或 setBackgroundImageNamed:方法來分配一個已經存在於Watch app資源包裏,或者是正在設備緩存中的圖像。
· 使用WatchKit的setImage:、setImageData:、setBackgroundImage:或setBackgroundImageData:方法無線傳輸圖像數據來擴展你的Watch app。
用命名指定圖像的好處是這些圖不須要再從用戶的iphone中無線傳輸到手錶。當你指定了圖片的命名,WatchKit只發送名稱字符串到你的Watch app中,這樣減小了時間和功耗。這個字符串用來檢索Watch app包中的圖像,或者從圖片緩存中去取得。
任什麼時候候你在你的擴展中建立的__UIImage__對象,必需要先將存在於用戶的iPhone上的圖像對象發送到Apple Watch上才能使用。甚至使用__UIImage__的 imageNamed:方法來加載你的WatchKit擴展包資源,也不是從Watch app中獲得的。
在設備上緩存圖像
若是你頻繁使用在你WatchKit擴展中建立的圖像,能夠把它們緩存到設備裏,而後經過名稱來引用。你必須在調用它們以前先緩存圖片,使用__WKInterfaceDevice__的addCachedImage:name:或addCachedImageWithData:name:方法。
使用緩存圖片須要注意如下兩點:
· 對於WKInterfaceImage對象,調用__setImageNamed: __方法,指定緩存圖像的名稱。
· 對於WKInterfaceGroup和WKInterfaceButton對象,調用__setBackgroundImageNamed:__方法,指定緩存中的名稱
Apple Watch圖像的緩存是限制尺寸的,每一個app大概可得到20MB的緩存空間。緩存是持久的並能夠在啓動的Watch app之間使用。當你達到最大緩存時,WachKit會丟棄比較老的圖像,把空間讓給新分配的圖像。
使用table展現內容可動態更改的列表數據。WatchKit 僅支持使用WKInterfaceTable類的單列表格。想要在table中展現數據,須要先爲數據定義佈局,並在運行時經過編碼填寫表數據。您須要在Xcode工程中作如下事情:
在storyboard文件中:
給界面控制器場景添加table對象,並在界面控制器中爲table建立一個outlet。
像Configuring Row Types描述的那樣爲table配置一個或多個row types。
在代碼中:
爲依照Configuring Row Types定義的row type定義一個row controller 類。
在初始化階段,依照Configuring the Table's Contents at Runtime向table中添加行
按照Handling Row Selections所述響應用戶與表格行的交互。
您能夠爲每一個table定義多個行類型,每種類型都有不一樣的外觀。在運行時,您能夠指定所需行類型以及它們在table中的排列順序。對於如何配置table的詳細信息,請參看WKInterfaceTable Class Reference.
配置Row Types
Row Type是一個在table中以單行形式展現數據的模板。每一個table必須至少有一個row type,您能夠根據需求定義額外的row type。您能夠用row type區分table中的不一樣內容。好比您可能在內容行上、標題和註腳上使用不一樣的類型。當您爲界面控制器場景添加table時,Xcode會自動建立 初始的row types供您配置。
爲table添加row types:
在storyboard文件中選中table對象
打開Attributes inspector.
使用Rows屬性更改可用row type數量。
每一個row type最初都包含一個單個組元素。您能夠爲該組元素添加標籤、圖片以及其餘所需對象。標籤和圖片的真實內容一般是可有可無的。在運行時,做爲配置工做的一部分,您能夠替換界面對象的內容。
想 要在運行時管理表格行的內容,您須要提供一個自定義的row controller 類。大部分row controller類包含少許代碼,或者根本就不包含代碼,它們主要用來訪問那些包含界面對象的outlets。不過,若是您在表格行中添加了按鈕或者 其餘控件,那麼其類也會包含一些動做方法,以響應用戶與控件的交互。
爲row type定義一個row controller類:
爲WatchKit擴展添加一個新的Cocoa Touch類
讓新類繼承NSObject。
爲每一個計劃在運行時訪問的標籤、圖片或者控件添加聲明的屬性。聲明屬性可以使用如下格式,請更改類以匹配相應的界面對象:
@property (weak, nonatomic) IBOutlet WKInterfaceLabel* label;
Listing 10-1 展現了一個用於管理row type的示例類
@interface MainRowType : NSObject @property (weak, nonatomic) IBOutlet WKInterfaceLabel* rowDescription; @property (weak, nonatomic) IBOutlet WKInterfaceImage* rowIcon; @end
您能夠在storyboard文件中完成row type配置。配置表格行要求設置其類,並將任何outlets鏈接到對應的界面對象上。您還必須提供一個方法,以便經過命名row type在運行時辨別表格行。
在storyboard中配置row type:
在storyboard文件中選中row controller對象。
將row controller的Identifier屬性設置爲惟一值,隨後您會在建立表格行時使用該標識符。
在行類型中該值必須是惟一的,可是實際值仍是由您來定奪。在Attributes inspector中設置該值。
將row type的類設置爲您的自定義類。您須要在Identity inspector中設置類信息。
將row type元素和類中對應的outlets鏈接起來。
將storyboard文件中的項目和outlets鏈接並綁定。當您在代碼中配置table時,WatchKit會在運行時使用該信息實例化對應的類。
Figure 10-1 在Xcode中配置一個命名爲"Main Row Type"的row type,並設置爲使用Listing 10-1中定義的MainRowType類。該類中的rowDescription 和rowIcon outlets被鏈接到行中的圖片和標籤。
運行時配置table內容
在運行時,您能夠爲table添加表格行並以編程形式配置其內容。一般,添加並配置表格行是初始化界面控制器過程當中的一部分。
建立並配置列表行
先決定你須要建立的行的數目和類型,這取決於你想要展現的數據類型。
使用setRowTypes:或者setNumberOfRaws:withRowType:方法來建立。這兩個方法都會在界面上建立新的列表行,而且會在WatchKit擴展中實例化對應的類。這些實例被保存在table中,且可經過rowControllerAtIndex:方法訪問。
使用rowControllerAtIndex:方法遍歷表格中的每一行。
使用row controller對象來配置每一行中的內容。
setRowType: 和setNumberOfRaws:withRowType:方法實例化與storyboard文件中對應的行類型相關的類。在調用這些方法以後,緊接着 就能夠直接獲取最新建立的row controller對象了,固然還能夠經過這些對象來設置內容。下面的Listing 10-2這段代碼則是一個能建立新行並對其進行配置的簡單示例。在這個例子裏,使用的是在代碼Listing 10-1中定義的MainRowType類,以及自定義的MyDataObject類,MyDataObject類用於提供table中用於行內容的數 據。在setNumberOfRaws:withRowType:方法中設置好數據對象以後,代碼會遍歷該對象,並使用它們配置表格中每一行的內容。
Listing 10-2 建立並配置table中的行
- (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]; } }
表格行的選中處理
界面控制器負責處理table中的行選中操做。當用戶點擊table中的某一行,WatchKit會選中該行並調用WatchKit擴展中正確的方法。您能夠在如下地方處理表格行的選中操做:
界面控制器的table:disSelectRowAtIndex:方法中。
界面控制器自定義的動做方法中。
您可使用以上二者之一來處理行選中事件。若是您的界面控制器有多個table,那推薦使用一個動做方法,由於您無需斷定操做跟哪一個table有關。若是您使用了一個動做方法,那須要遵循下面的語法:
- (IBAction)myTableAction:(NSInteger)rowIndex
經過選中表格行來執行app相關的任何操做,好比跳轉新界面,或者更新行中顯示的內容。若是您不但願用戶選中表格行,能夠在Storyboard中禁用相應的row controller的Selectable選項。
六.Watch Apps--情景菜單
Apple Watch上Retina屏的Force Touch特性提供了與內容進行交互的新途徑。與點擊屏幕上的項目不一樣,該特性並不是輕觸,而是須要必定的按壓力度才能激活與當前界面控制器相關的情景菜單。
情景菜單是可選的。使用情景菜單來展現當前屏幕相關的操做,圖11-1展現不一樣數量操做下的情景菜單。
情景菜單能夠展現4項操做。每一個操做由一個標題和一張圖片表示。點擊屏幕上某張圖片可執行對應的操做,點擊屏幕上任何其餘地方便可解除菜單。
設計菜單項
每一個菜單項包含一個可點擊區域和一個標題。可點擊區域由純色背景和您提供的圖片組成。圖片必須是模板圖片,其alpha通道指定了繪製在純色背景
上的圖形。模板圖片的不透明部分在背景上顯示爲黑色,所有或者部分半透明部分可透露出背景的顏色。
圖11-2展現了菜單項目的圖片和標題的佈局。您提供的模板圖片實際上應當比背景小一點。更多關於圖片尺寸的信息和如何建立圖片的指南,請參看Apple Watch Human Interface Guidelines.
圖11-2 菜單項目佈局
爲界面控制器添加情景菜單
你能夠以編程方式或者在設計階段配置情景菜單。您添加到storyboard中的菜單項是持久性的不能在運行時移除。您經過編程方式添加的菜單項能夠被移除。使用WKInterfaceController類的方法來添加或者移除新的菜單項。
重要:情景菜單中的菜單項目總數不能超過4個,無論是在storyboard文件中定義仍是以編程方式添加,或者組合兩種方式。
向界面控制器中添加情景菜單須要:
1.打開storyboard文件。
2.從工具庫中拖拽一個菜單項,並將其添加到界面控制器場景中。初始菜單包含一個單獨的菜單項目。
3.最多從庫中拖拽3個菜單項到菜單中。你還可使用菜單的Attributes檢查器來設置菜單項數量,您添加的菜單項不能被移除。
4.對於每一個菜單項目,可以使用Attributes檢查器來指定菜單的標題和圖片,這二者都是須要的。
5.在界面控制器類中將每一個菜單項和操做鏈接起來。菜單操做方法格式以下:
- (IBAction)doMenuItemAction
想要在運行時添加菜單項目,請調用界面控制器對象的addMenuItemWithImage:title:action:或者addMenuItemWithImageNamed:title:action:方法。您添加的菜單項被附加到storyboard文件中指定的對象上。以編程方式添加的菜單項目持續附屬於菜單,直到您明確地移除它們或者您的界面控制器解除配置。
當 用戶點擊菜單項目時,WatchKit則調用界面控制器中定義的關聯動做方法。經過動做方法的實現來執行用戶請求的操做。若是要求使用任何狀態信息來執行 操做,那麼您須要在界面控制器中保持所需狀態。好比,若是一個動做依賴於表格中當前的選中行,那麼您的界面控制器必須包含一個變量來跟蹤當前選中的行。
C.Glance
一.Glance開發基礎
Glance是Apple Watch三種用戶交互之一,就和它的字面意思同樣,它將重要信息展現在一個視圖裏,讓用戶能在一瞥之間快速獲取,是對一個完整的Watch app的有益補充。
一個Glance是用戶瀏覽Watch app中的重要信息的補充方式,它對於Watch app並非必需的。Glance應該及時的提供直接相關的信息。好比,一個日曆應用的glance能夠展現用戶的下一場會議,而一個航班應用的 glance可以展現你要搭乘班機的登機口信息。圖片12-1顯示了Lister示例應用的glance,它顯示用戶to-do列表的已完成和剩餘項目的條數。
圖片12-1 Lister示例應用的Glance界面
Glance是Watch app和WatchKit擴展的一部分,你的glance界面位於Watch app的storyboard文件當中,而且這個界面被自定義的WKInterfaceController對象管理。須要注意的是,這個glance界面控制器只負責設置glance中的內容,Glance不支持互動操做,觸摸glance將會自動啓動對應的Watch app。
Glance的生命週期
Glance界面控制器的生命週期和其餘WatchKit界面控制器同樣,不過glance的界面控制器的初始化要早於其它,以便於glance能快速的顯示給用戶。考慮到glance從初始化到顯示可能會花費一些時間,可能讓信息過期,你須要在willActivate方法中包含檢查,以確保顯示的信息是最新的。
如需獲取界面控制器的聲明週期信息,閱讀WatchKit Extension Life Cycle。
Glance界面指南
Xcode提供幾種固定的佈局來安排glance中的內容,在選定適合你的一種佈局後,遵循下面的指南來填充內容:
· Glance的設計目的在於快速的傳達信息。不要顯示一堆文字。適當的使用圖像、顏色和動畫來快速傳達信息。
· 聚焦在最重要的數據上。Glance不是你的應用的替代。就像Watch app是對應的iOS app的縮水版,你也能夠把glance看作Watch app的縮水版。
· 不要在glance界面中包含交互控件。好比按鈕、選擇器、滑動器和菜單。
· 避免使用表格和地圖。儘管並無禁止你這麼作,手錶上有限的空間讓表格和地圖不是那麼有用。
· 讓顯示的信息保持及時。使用全部可用的資源,包括時間和地理位置,來向用戶提供有用的信息。而且注意更新你的glance,以免由於glance初始化到顯示花費的時間而讓信息過期。
一個app只容許有一個glance界面控制器,所以你須要在這一個控制器中顯示全部你但願展現的內容。
二.管理你的Glance界面
當添加Watch app target到你的Xcode工程當中時,你能指定是否須要一個glance界面。若是你在一開始忘了添加,也能稍後向工程中加入glance。一個 glance界面控制器在storyboard中的顯示有些不同的地方,特別是,它有一個Glance入口點對象,就像圖片 13-1顯示的同樣。
圖片 13-1 一個擁有glance入口點對象的界面控制器
Glance界面由自定義的WKInterfaceController
子類驅動,此子類的實現方式和其餘界面控制器類相同。
實現一個Glance界面控制器
Glance界面控制器的具體實現比較簡單,由於它惟一的任務是設置glance中的標籤和圖像內容。因此你的glance基本上只須要實現兩種方法:
使用initWithContext:
方法來初始化你的glance界面,而且設置標籤和圖像的初始值。
基於內容的改變,使用willActivate
來更新glance。
當glance已經顯示給用戶後,如需更新,使用NSTimer
對象,你也能使用WKInterfaceDate
和 WKInterfaceTimer
類來顯示日期和時間信息,以及倒計時或者顯示特定時間。
自定義從Glance啓動應用
當用戶觸摸glance,Apple Watch可以啓動對應的Watch app。通常來講,啓動app將顯示它的主界面控制器。若是你想顯示一個不一樣的界面控制器,調用你的glance界面控制器的updateUserActivity:userInfo:
方法。
調用updateUserActivity:userInfo:
方法將告訴WatchKit來請求啓動時須要顯示的界面控制器。在啓動進程當中,WatchKit調用主界面控制器的actionForUserActivity:context:
方法來找出到底須要顯示哪一個界面控制器。在你的Watch app的主界面控制器裏實現這個方法,並讓它返回你須要的界面控制器名稱。經過這個方法,你也能提供一個上下文對象,並將它做爲參數傳遞給指定的界面控制器的initWithContext:
方法。
總結一下,爲了在觸摸glance時啓動並顯示一個不一樣的界面控制器,你須要按以下步驟操做:
在glance界面控制器中:
配置glance的initWithContext:
和 willActivate
,這一步和其餘狀況是相同的。
調用updateUserActivity:userInfo:
方法,而且使用userinfo
參數來傳達你的應用glance的狀態。
在你的應用的主界面控制器:
實現actionForUserActivity:context:
方法,使用提供的userinfo
字典來肯定顯示哪一個界面控制器,你還應該生成一個上下文對象並將它傳遞給指定的界面控制器。
D:通知
一.有關通知的一些要點
若是您的 iOS 應用支持本地或遠程通知,Apple Watch 也會同步顯示這些通知。當某個應用的本地或遠程通知抵達用戶的 iPhone 後,iOS 將會自行判斷顯示該通知的設備(iPhone 仍是 Apple Watch)。對於發送到 Apple Watch 的通知來講,系統首先會暗示用戶該通知已經送達。若是用戶選擇查看這個通知,系統將會首先展現該通知的概覽。若是用戶選擇繼續瀏覽這個通知,系統將會顯示 其具體信息。藉助上述功能,用戶能夠選擇忽略該通知,也能夠選擇單擊某個可用的按鈕(若是存在的話)來查看該通知或者啓動您的應用。
要支持通知的話,應用其實並不須要面面俱到。系統提供了一個默認通知界面以展現來自通知的提醒信息。而後,應用能夠自定義這個通知界面,同時向裏面添加自定義圖形、內容,甚至商標。
提示:要了解更多關於 iOS 應用是如何支持通知的信息,請參閱 Local and Remote Notification Programming Guide
Short-Look 界面
當 用戶第一次看通知的時候,系統將會顯示這個 Short-Look 界面,圖14-1顯示了一個大概的例子。Short-Look 界面是一個不可滾動的視圖,而且不能夠被定製。系統使用一個通用的模板來顯示應用名稱、圖標,以及存儲在本地或遠程通知消息中的標題。若是用戶一直在查看 這個通知,系統將會迅速將 Short-Look 界面轉變爲 Long-Look 界面。
Long-Look 界面
Long-Look 界面是一個可滾動的界面,它顯示了通知的所有內容,以及全部的關聯按鈕。若是您沒有提供自定義的通知界面,那麼 Apple Watch將會顯示默認界面,裏面包括了應用圖標、通知的標題,以及提示消息。而若是您提供了自定義的通知界面,那麼 Apple Watch 將會顯示它。
Long-Look 通知界面分爲三個區域:
· 窗扇是一個包含有應用圖標和應用名稱的區域。窗扇的背景默認狀況下是透明的,可是您能夠在自定義通知界面中改變它的背景顏色。
· 內容區域包含有即時通知的詳細內容。對於自定義界面來講,您能夠配置該界面的起始位置,是從窗扇頂部開始,仍是在窗扇下面開始。要了解更多關於如何自定義這個區域的內容,請參閱 Custom Notification Interfaces
· 按鈕區域包含有一個取消按鈕和其餘您應用定義的按鈕。取消按鈕是系統提供的,而且不能夠刪除它。
圖14-2展現了一個包含有兩個按鈕的Long-Look通知界面示例。
圖14-2 Long-Look 通知界面
單 擊窗扇區和內容區的任意位置都將啓動您的應用。單擊任何一個由您應用定義的按鈕都將啓動 WatchKit 擴展或者 iOS 應用,而後向其傳遞動做信息。發送給 WatchKit 擴展的是前臺動做,而發送給 iOS 應用的是則後臺動做。單擊取消按鈕將會直接關閉這個通知。
欲瞭解如何製做一個自定義 Long-Look 界面,請參閱 Custom Notification Interfaces
爲通知上添加按鈕
按鈕經過爲通知提供封裝的動做響應來幫用戶節省時間。Apple Watch使用iOS 應用註冊的交互通知界面來顯示按鈕。在 iOS 8 以及更高版本中,應用都須要使用UIUserNotificationSettings 對象來註冊它們顯示的生成通知對話框。一旦對象建立,應用也一樣能夠指定自定義通知類別以及其對應的按鈕動做。Apple Watch使用這個類別信息來添加相應的按鈕到 Long-Look 界面上。
代 碼列14-1顯示了一個方法的部分實現代碼,其用來爲一個示例應用註冊設置及類別。這個方法在containing iOS app中聲明,而不是在 WatchKit 擴展中聲明,而且它在啓動時被 iOS 應用委託調用。這個實現代碼展現了「invitation」類別的建立和註冊,其包含了接收或拒接會議邀請的按鈕動做。
代碼列14-1 在iOS 容器應用(containing app)中註冊按鈕動做
- (void)registerSettingsAndCategories { // Create a mutable set to store the category definitions. NSMutableSet* categories = [NSMutableSet set]; // Define the actions for a meeting invite notification. UIMutableUserNotificationAction* acceptAction = [[UIMutableUserNotificationAction alloc] init]; acceptAction.title = NSLocalizedString(@"Accept", @"Accept invitation"); acceptAction.identifier = @"accept"; acceptAction.activationMode = UIUserNotificationActivationModeBackground; acceptAction.authenticationRequired = NO; UIMutableUserNotificationAction* declineAction = [[UIMutableUserNotificationAction alloc] init]; declineAction.title = NSLocalizedString(@"Decline", @"Decline invitation"); declineAction.identifier = @"decline"; declineAction.activationMode = UIUserNotificationActivationModeBackground; declineAction.authenticationRequired = NO; // Create the category object and add it to the set. UIMutableUserNotificationCategory* inviteCategory = [[UIMutableUserNotificationCategory alloc] init]; [inviteCategory setActions:@[acceptAction, declineAction] forContext:UIUserNotificationActionContextDefault]; inviteCategory.identifier = @"invitation"; [categories addObject:inviteCategory]; // Configure other actions and categories and add them to the set... UIUserNotificationSettings* settings = [UIUserNotificationSettings settingsForTypes: (UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:categories]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; }
要了解如何在 iOS 應用中配置類別和按鈕動做的信息,請參閱 Local and Remote Notification Programming Guide
讓按鈕響應單擊動做
當用戶在通知界面裏面單擊按鈕時,系統使用在註冊過的 UIUserNotificationAction 對象裏面的信息,來決定了如何處理這個操做。按鈕動做能夠在前臺處理,也能夠在後臺處理,而且它能夠附帶或者不附帶用戶的認證信息。不過,前臺處理按鈕動做和後臺處理是有必定區別的:
· 前臺按鈕動做將啓動您的 Watch 應用,而後將按下的按鈕的 ID 傳遞給主界面控制器。
· 後臺按鈕動做將在後臺啓動 containing iOS app,以讓其來處理這個動做。被選擇動做的相關信息將被傳遞給應用委託中的application:handleActionWithIdentifier:forRemoteNotification:completionHandler:或application:handleActionWithIdentifier:forLocalNotification:completionHandler:方法。
對於前臺按鈕動做來講,要記住WKUserNotificationInterfaceController子類並不處理這個按鈕動做。選中一個前臺按鈕動做將啓動您的應用,併爲您應用的主入口點載入界面控制器。該初始界面控制器負責處理全部按鈕動做。這個界面控制器必須實現 handleActionWithIdentifier:forRemoteNotification:方法(若是適用的話)來處理和本地或遠程通知相關的按鈕動做。
二.自定義通知界面
自定義通知界面含有兩個獨立的界面:一個靜態界面,一個動態界面。動態界面顯示 了完整的自定義通知內容樣式,而且它能夠包含由 WatchKit 擴展提供的定製內容和圖形。靜態界面是一個簡單的界面,它僅僅只含有通知的提示信息,以及您在設計時配置的靜態圖像以及文本信息。
當 您在 storyboard 文件中添加新的通知界面控制器的時候,Xcode 將會建立一個獨立的 storyboard 場景,其中包含有一個動態界面和一個靜態界面,如圖15-1所示。靜態界面是必需的,若是須要的話您能夠刪除動態界面。若是靜態界面已經能夠顯示您想要的 所有信息,那麼您就能夠刪除動態界面。動態界面和靜態場景都和相同的通知類型相關聯,而這個通知類型能夠用來指定使用何種通知類別來關聯靜態界面。
圖15-1 靜態界面和動態界面
當 合適類型的通知抵達時,WatchKit便嘗試顯示動態界面。若是您並未提供靜態界面,或者出於某些緣由您的動態界面不可用,那麼Apple Watch 將會用靜態界面來代替。Apple Watch 一樣也會在您明白告知使用靜態場景時顯示靜態界面。配置動態界面須要調用didReceiveRemoteNotification:withCompletion:或didReceiveLocalNotification:withCompletion:方法。若是 這些方法使用WKUserNotificationInterfaceTypeDefault常量來調用完成處理程序的話,那麼 Apple Watch將會顯示靜態場景。
配置自定義界面的通知類型
每一個通知界面必須分配一個通知類型,以告知 Apple Watch 什麼時候使用它。到來的通知能夠在消息載體中包含類別值。Apple Watch 使用這些類別值來決定顯示何種通知場景。若是到來的通知並未包含類別值,那麼Apple Watch會展現一個類型被設定爲`default`的通知界面。
要給通知界面分配通知類型,請在 storyboard 中配置和場景對應的通知類別(Notification Catagory)對象。該對象的屬性檢查器含有一個Name 屬性,如圖15-2所示。在這個屬性中輸入通知類型的類別名稱。您一樣也可使用該對象來指定窗扇的顏色。每一個通知場景的Name 屬性不能相同。
圖15-2 配置通知類型信息
當生成遠程通知時,您的服務器要經過在其`aps`字典中包含category鍵的值來指定通知類型。`category`的鍵值要和您在 iOS 應用以及您在通知類別對象中的 Name 屬性指定的同樣。例如,在圖15-2中,類別文本是`MeetingInvite`。
提示:類別字符串一樣定義了被添加到通知界面末端的操做按鈕(若是存在的話)。欲瞭解關於支持自定義按鈕動做的更多信息,請參閱Adding Action Buttons to Notifications
配置靜態通知界面
使用靜態通知界面來定義一個自定義通知界面的基本樣式。使用靜態界面的目的是在 WatchKit 擴展不能及時配置動態界面的時候,提供一個回退界面。建立靜態界面的規則以下:
· 全部的圖像必須駐留在 Watch 應用包中
· 界面不能包含控件、表格、地圖,以及其餘交互元素
· 界面的`notificationAlertLabel`輸出口必須與某個標籤相關聯。標籤的文本設置爲通知的警告信息。其餘的標籤文本不變,而且只可以在設計時設置。
圖15-3顯示了在一個日曆應用當中的靜態和靜態場景,其使用了自定義通知界面。通知箭頭指向了靜態場景,其中包含了自定義圖標和兩個標籤。「Message」標籤和`notificationAlertLabel`輸出口鏈接,所以它將在運行時接收通知的警告信息。
圖15-3 單一通知類型的靜態和動態場景
除了和`notificationAlertLabel`輸出口相連的標籤外,在靜態通知場景中的標籤和圖像是不可以改變的。當您在設計界面時請記住這條準則,並確保每一個標籤的文本是合適的。
配置動態通知界面
動態通知界面給用戶提供了一個更豐富的通知體驗。藉助動態界面,您能夠顯示不少的內容。您能夠添加額外的信息,配置多個標籤,動態地生成內容,等等。
實現動態通知界面須要建立一個自定義的WKUserNotificationInterfaceController子類。該子類的實現代碼負責在通知須要顯示時配置界面。
設計動態界面
配置動態界面和配置其餘界面控制器場景十分類似。
您能夠在子類中包含標籤、圖像以及場景中的其餘對象,並使用這些輸出口以在運行時配置場景的內容。單擊通知界面將啓動應用,所以通知界面不該當包含交互控制。
· 可在絕大多數界面上使用標籤、圖像、組以及分隔符。
· 您可能想要在須要的時候使用表格和地圖。
· 不要包含有按鈕、開關,或者其餘交互控件。
在運行時配置動態界面
界面初始化以後,WatchKit將負載數據傳輸到通知界面控制器的不一樣方法中。對於遠程通知來講,WatchKit 調用didReceiveRemoteNotification:withCompletion:方法。對於本地通知來講,它調用didReceiveLocalNotification:withCompletion:方法。請使用接受到的數據來配置您的通知界面。界面配置完成後,您必需要調用所提供的完成處理代碼塊來讓 WatchKit 知道您的界面已經準備就緒。圖15-4顯示了處理遠程通知的初始化和配置進程。
圖15-4 顯示自定義通知界面
始終選擇使用 didReceiveRemoteNotification:withCompletion:和 didReceiveLocalNotification:withCompletion:方法來配置您的通知界面。當實現完這兩個方法後,儘快運行所提供的完成處理方法來配置界面。而後儘快運行這個代碼塊。若是您等待了太長時間,那麼Ale Watch將會使用靜態界面。
代 碼錶15-1顯示了`didReceiveRemoteNotification:withCompletion:`方法的實現例程。這個方法被一個發送 遠程通知的虛構日曆應用所實現,用來提示某個新的會議邀請。這個方法從遠程通知負載中獲取數據,而後使用這個數據來設置通知界面的標籤值。爲了簡便,這個 示例假定服務器發送的鍵值中都有合適的對應值,可是您本身的代碼應該執行必要的錯誤檢查,來保證複雜數據是由有效的。在配置完標籤後,這個方法將調用完成 處理器,來讓 WatchKit 知曉自定義界面已經就緒。
代碼表15-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的內容。
測試您的自定義界面
當您準備在模擬器測試您的自定義界面時,若是您尚未肯定擴展已製做完成的話,請建立一個自定義編譯方案來運行您的通知。使用 Xcode 模板提供的`RemoteNotificationPayload.json`文件來指定您的負載數據。要了解更多關於設置編譯方案以及配置負載數據的內 容,請參閱The Build, Run, Debug Process。