iOS開發(fā)者須知 :WatchKit開發(fā)技巧
從一月中旬以來我全身心投入到 WhereNotes App 的Apple Watch部分的工作中。我也有幸被邀請到在Cupertino 的Apple Watch 實驗室。在過去的三個半月中,我搜集了很多技巧,并在這篇文章中涵蓋了它們中的大部分。我希望這些技巧能夠?qū)δ愕腁pple Watch開發(fā)有所幫助。
也許你對于這些如applicationWillEnterForeground:和applicationDidEnterBackground:方法非常熟悉。它們在與之相對應的通知(UIApplicationWillEnterForegroundNotification和UIApplicationDidEnterBackgroundNotification)前被調(diào)用。與之相等價(鮮有人知)的WatchKit NSExtensionContext通知如下:
NSExtensionHostWillEnterForegroundNotification?
NSExtensionHostDidEnterBackgroundNotification?
NSExtensionHostWillResignActiveNotification?
NSExtensionHostDidBecomeActiveNotification
我與大多數(shù)蘋果開發(fā)者社區(qū)中的成員都有這樣的經(jīng)驗,用一個在充電器上的Watch測試會獲得更好更可靠的調(diào)試經(jīng)驗。
在iOS上可以隨時更新界面元素,但是在WatchKit上,只能更新當前激活的、可視的視圖控制器中的元素。直到didDeactivate方法被調(diào)用時,更新才能被安全的執(zhí)行。(注意你不能在此方法中更新界面元素)這意味著如果你打算更新一個當前隱藏的視圖控制器(例如你正在查看最頂部的模態(tài)控制器),你會需要執(zhí)行當前控制器的willActivate方法,這個方法會在模態(tài)控制器消失的時候被調(diào)用。
除包含在你的Watch app bundle中的assets之外,每個app 只允許5MB的高速圖片緩存,通過extension使用 WKInterfaceDevice 中的方法引入和管理圖片緩存。從extension發(fā)送圖片到watch端需要消耗時間和電池電量,所以需要重用圖片(即使只是用一次),這都是值得緩存的。如果使用 addCachedImage:name: 發(fā)送一張圖片,那么這張圖片會自動的被以PNG格式編碼,并發(fā)送到緩存中。不論PNG是否是最佳的格式(但這是最安全的格式)。如果你的圖片能以JPG的格式呈現(xiàn),我強烈地推薦使用addCachedImageWithData:name: 來取代上述方法。以JPG格式編碼圖片和試用圖片質(zhì)量設(shè)置,不僅圖片將會更快速地傳輸,同時也會擁有更多的緩存空間用于儲存更多的圖片。
依據(jù)之前的建議,你可以在后臺進程緩存圖片(依據(jù)一個在開發(fā)者社區(qū)中的蘋果雇員所述)。我在我的Watch app中,使用提前緩存圖片這項技術(shù)。
如果你使用前邊提及到的圖片緩存,這里沒有內(nèi)置方法決定刪除使用過最舊的圖片。如果你的app管理了許多圖片,你會想要封裝關(guān)于緩存的manager。
為了測試Apple Watch上的通知,在Apple Watch配對的app的通用中設(shè)置關(guān)閉手腕檢測。
想要強制退出app,按住旁邊的按鈕,一段時間后再次按住它(注意強制退出你的app不會強制退出你的extension)。
在willActivate中最小化處理的工作,以減少加載等待時間。
考慮用戶在使用iPhone app之前打開你的Watch app以及設(shè)計的一致性。App審核會發(fā)現(xiàn)這些情況。
記住你的Watch app 是以extension的方式運行。你的Watch app的內(nèi)存限制要比iPhone app要更為嚴格。如果處理大量的圖片,在iPhone app上完成此項工作會更好(使用openParentApplication:reply:)。還得注意模擬器不會執(zhí)行這些內(nèi)存限制,所以必須在真實地設(shè)備上進行測試。
為了發(fā)現(xiàn)你的app是否與Watch匹配,為Watch app共享的NSUserDefaults(使用 shared app group)設(shè)置BOOL值,你的iPhone app能夠獲取它。
為了同步在iPhone與Watch之間的數(shù)據(jù),你可以調(diào)用你的iPhone app執(zhí)行所有的數(shù)據(jù)更新(使用 openParentApplication:reply:),或使用 Darwin notifications 在extension和iPhone app之間發(fā)送事件。Darwin notifications不支持數(shù)據(jù)裝載,所以如果你想通過通知傳輸數(shù)據(jù),可以查看非常有用的 MMWormhole 工程。
你除了使用timer更新和刷新界面元素,還可以使用KVO,如果你的數(shù)據(jù)源支持。這就是我在我的Watch app中所使用的方法。使用這種方法,界面元素只會在它們改變的時候被更新,同時降低通訊消耗和節(jié)省電池電量。
如果你需要跟蹤控制器界面,在 awakeWithContext: 中考慮給self傳輸引用建立關(guān)系。我已經(jīng)在我的app中通過我的 JBInterfaceController subclass 大量地使用這種模式。使用類似這類的技術(shù)讓你如使用代理模式一樣去工作。同時,更多以類似UIViewController方式考慮你的controller。
WatchKit extension是前臺的extension,所以如果你需要獲得 Core Location 的授權(quán)允許,你只需要在授權(quán)需要時請求。
除非你的場景需要,必須謹慎考慮你是否需要“在線更新”,即在Watch和iPhone之間立即同步。用戶通常不會同時使用兩個設(shè)備,所以在下一次Watch或iPhone app激活時簡單地更新數(shù)據(jù)就能避免大量的同步邏輯。不幸的是看著watch與iPhone的模擬器的屏幕緊鄰彼此,就很有可能去建立復雜的同步邏輯。也許我做了,但我沒有告訴你。
當你不能用程序創(chuàng)建和控制視圖控制器時,你能明智地了解你是如何隱藏和顯示視圖元素。這會成為一個通用地WatchKit實踐,例如,建立一個全頁的label,如果有一則重要的消息需要展示時它可以被顯示?;蛘撸绻阌袃蓚€你需要編程選擇的布局,可以包含它們到最上層的組,并在需要的時候讓其隱藏和顯示。
記住每個屏幕的觸摸和界面更新需要Watch和iPhone之間來回的通訊。
WatchKit界面元素是只寫的(它們通常也有setter方法),這需要手動跟蹤你已經(jīng)設(shè)置后你不想再次設(shè)置的值。WatchKit嘗試在每次run loop合并值以及只發(fā)送最后的值,但你也能參與其中跟蹤你自己的值。
然而這里沒有內(nèi)建的活動指示控件,當進行一項長時間的處理時(如圖片傳輸或下載),你可以顯示一系列的動態(tài)圖片。更新于5/3/2015:我剛在GitHub發(fā)布了JBWatchActivityIndicator 工程,它使得創(chuàng)建活動指示圖片序列更加容易。它也包含了一些蘋果風格的預先渲染的序列。
確認下載和查看Apple Watch Design Resouces。除了有用的顏色和尺寸的推薦外,也包含了用于市場截圖的高質(zhì)量圖片。正當我說著這個話題時,你提交的app截圖不包含bezel 圖片是沒有價值的。
許多開發(fā)者對于模擬器上圖片展示正確,但在真實的watch上卻不一致的情況表示沮喪。事實上這是許多App被拒絕的原因。這個問題的出現(xiàn)與文件命名和文件丟失有關(guān)。最安全的解決辦法是在Watch app中(不是extension)的assets library 中包含所有的圖片。這就是我在我的Watch app中所作的。我推薦你也使用同樣的方法。
雖然能從Watch加載你的iPhone app到前臺是一個非常常見的需求,但通過編程無法實現(xiàn)(即使有方法可以在模擬器上運行),考慮用 Handoff 取代。
如果你需要在兩個視圖控制器間傳遞信息,但你不能通過 awakeWithContext: 完成,考慮使用發(fā)送 NSNotifications。在extension中它們運行良好。否則遠程指定克隆我的JBInterfaceController subclass,并使用代理模式。
本地通知要求設(shè)置 soundName 屬性以生成觸覺反饋和鈴聲。
模擬器是好的開始,但在真實硬件設(shè)備上測試你的app才是關(guān)鍵。