自一月中旬以來,我就全身心投入到WhereNotes應用的Apple Watch版本的開發上了,並幸運地受邀參加了庫比蒂諾蘋果總部的Apple Watch實驗室測試。在過去的三個半月裡,我整理了諸多WatchKit的開發建議和技巧,並將重點內容列在這裡,希望對Apple Watch應用開發者有所啟發。
1. WatchKit的NSExtensionContext通知
可能對諸多開發者來說,UIApplication上的函式方法並不陌生,比如applicationWillEnterForeground:和applicationDidEnterBackground:,兩者都是先被呼叫,再分別發出UIApplicationWillEnterForegroundNotification和UIApplicationDidEnterBackgroundNotification的通知。而WatchKit的 NSExtensionContext通知則包括:
- NSExtensionHostWillEnterForegroundNotification
- NSExtensionHostDidEnterBackgroundNotification
- NSExtensionHostWillResignActiveNotification
- NSExtensionHostDidBecomeActiveNotification
2. 充電測試更有效
在Apple Watch充電時進行測試,測試過程更容易,結果也更可靠,這一點不僅僅是我,其他Apple開發者論壇上的同行也深有體會。
3. WatchKit只能在當前活動/可見的檢視控制器上更新
在iOS上幾乎可以隨時更新介面元素,但WatchKit只能在當前活動/可見的檢視控制器上更新。只要didDeactivate還沒有呼叫,就能順利完成更新(注意:介面元素不能用didDeactivate更新)。這也就意味著:開發者想 要更新一個當前隱藏起來的檢視控制器(比如檢視一個模態控制器“on top”),就必須用當前控制器的willActive方法來更新,而willActive只有在取消(dismiss)模態控制器時才能被呼叫。
4. addCachedImage:name預設使用PNG編碼
除了WatchKit應用捆綁包裡的資源,每個應用還享有5MB容量的圖片快取空間,用WKInterfaceDevice上的方法來放置擴充套件,並用擴充套件進行管理。從擴充套件向Watch傳送圖片會消耗時間和電量,所以如果要再次使用某張圖片(即使只用過一次),最好將它快取起來;如果用addCachedImage:name:來傳送圖片,它會自動以PNG格式快取起來(也許PNG格式並不是最合適的,但至少是最保險的)。如果圖片能以JPG格式再次呈現的話,那麼建議改用addCachedImageWithData:name: 來傳送。以JPG格式儲存圖片後再試試畫面設定,圖片轉換不僅更快,還省下了不少快取空間,方便儲存更多圖片。
5. 支援後臺執行緒快取影像
依然跟上一條建議相關:開發者可以在後臺執行緒上快取圖片(開發者論壇的一名蘋果員工如是說)。我在開發Watch應用時嘗試了一下,圖片在讀取之前就快取好了。
6. 開發者需自行封裝圖片管理器
要使用上述的圖片快取的話,並無內建的方法來檢測最早的圖片。若應用同時管理很多圖片,可能需要在快取裡設立一個單獨的管理器。
7. 測試通知功能時記得關閉手腕感應
在Apple Watch上測試通知功能時,需要在其Companion(夥伴)應用的通用設定裡關掉Wrist Detection(手腕感應)。
8. 若要強制退出應用,長按側鍵開啟Friends應用
要強制退出應用,就單擊側鍵開啟Friends應用,然後再按一次(注意,強制退出應用不代表強制退出擴充套件)。
9. 儘可能地精簡willActivate操作,縮短載入時間。
10. 先Watch後iPhone App
如果使用者在你的iPhone應用之前搶先發布Watch App就不妙了,所以留點心,別讓蘋果的應用稽核快你一步發現問題。
11. 切忌處理大圖片
Watch應用是以擴充套件的形式執行的,其本身記憶體相比iPhone應用更受限制,所以像是稍大點的圖片,還是留給iPhone應用處理就好(用openParentApplication:reply:)。還要注意,模擬器不受記憶體限制,所以最好還是在真機環境中進行測試。
12. 通過共享NSUserDefaults設定布林值檢測匹配
要測試應用是否跟Watch匹配,可以在共享應用組中通過共享NSUserDefaults設定一個布林值來進行檢測。
13. 實現iPhone與Apple Watch的資料同步
要想實現iPhone和Watch的資料同步,要麼用openParentApplication:reply:來讓iPhone應用執行所有資料更新,要麼使用Darwin notifications在擴充套件和iPhone應用之間傳送事件。Darwin notifications不支援資料負載,如果想用通知來傳送資料的話,可以看一看 MMWormhole通訊框架,你會有所啟發。
14. 定時器重新整理介面元素
可以用定時器(或在willActive裡)更新和重新整理介面元素。當然,在資料來源支援的情況下也可以用KVO。我在開發Watch應用時運用了KVO,用這個方法,元素只有在產生變化時才更新,這樣能節省傳輸負載和電量。
15. awakeWithContext傳self指標很有用
若要追蹤檢視控制器,可以考慮用awakeWithContext來傳遞self指標。
16. when-in-use
WatchKit擴充套件是前臺擴充套件(foreground extension),所以在用到Core Location許可時,只需傳送一個when-in-use(使用時)認證請求就好。
17. 少用“實時更新”
除非萬不得已,否則不要使用”實時更新(live update)“,使iPhone和Watch即刻同步。使用者一般不會同時使用兩個裝置,所以在iPhone或Watch啟動時更新資料,足以避免諸多混亂的同步邏輯。可惜,一看到並列的模擬器螢幕就想設立複雜的同步邏輯,我就幹過這樣的事兒。
18. 用hide/unhide程式碼構建動態檢視介面
雖然無法用程式建立和管理介面控制器,但hide/unhide元素還是盡在掌控的。舉個例子,WatchKit最常見的操作之一就是構建一個可以顯示所有資訊的頁面。或者在程式設計中,如果要在兩個佈局中選其一,那麼可將其安放在top-level group裡,僅在必要時顯示或隱藏。
19. 每次螢幕點選和介面更新都需要Watch與iPhone的往返通訊,在程式設計時要考慮到這一點。
20. 記錄值決定再次寫入更新
由於WatchKit介面元素的“只寫”特性(只能設定函式),開發者不需要二次設定追蹤記錄的值,而WatchKit還能對值進行合併,只在執行迴圈交接時傳送最終值,但亦可自行追蹤。
21. 無內建的進度指示器
Watch並沒有內建的進度指示器控制元件,但系列動畫影像的顯示和持續的圖片轉換下載依然能同時進行。操作結束時,直接隱藏進度指示器圖片即可。在此,大家可以嘗試一下我剛剛在GitHub上更新的JBWatchActivityIndicator,它能讓建立活動指示器圖片序列變得更簡單,預先渲染的類蘋果序列也包含在內。
22. 一定要充分利用Apple Watch Design Resources
開發Apple Watch應用,一定要下載 Apple Watch Design Resources並認真閱讀,裡面除了顏色和尺寸建議外,優質的邊框圖片還可以截下來給應用打廣告。說到這裡注意一下:提交的應用截圖是不能帶邊框的。
23. 解決真機圖片顯示異常問題
圖片在模擬器裡顯示正常,但在真正的Watch上卻出了問題,讓開發者們叫苦不迭,實際上這也是諸多應用被拒的根本原因。問題就出在檔案命名和”零散“的圖片檔案上,而最保險的辦法就是在Watch 應用(非擴充套件)的target裡建個assets來儲存所有影像。
24. 使用Handoff讓iPhone應用前臺啟動
目前,還沒有明確的辦法可以直接通過Watch前臺啟動iPhone應用(雖然可以在模擬器上實現),所以,還是考慮使用蘋果的Handoff來代替吧。
25. 控制器間使用NSNotifications通訊
在檢視控制器之間的通訊最好別用awakeWithContext:,傳送NSNotifications好一些,在擴充套件裡執行更流暢。也可以看看我開源的WKInterfaceController子類 JBInterfaceController,使用委託模式。
26. 本地通知需要設定soundName屬性來觸發Tapic反饋和提示音。
27. 真機測試很重要!
從模擬器入手是挺好,但是在真機環境中測試自己的Watch應用才是最關鍵的一步(甚至比測試iPhone或iPad應用更重要)。