Apple Watch已經上市一段時間,在探究其防盜、防水等眾多功能的同時,Apple Watch版應用開發也在不斷的摸索前進中。在本文中,來自國外的知名iOS開發大牛就Watch版應用開發過程中遇到的問題以及犯下的錯誤進行了分享。
Natasha Murashev——Capital One iOS工程師、Natasha The Robot博主
我犯過的大錯誤就是認為在Apple Watch上發送信息就可以打開iOS App。WatchKit有一個支持直接發送信息到iOS應用的API,能夠有效地觸發后臺進程。想要啟動時只需調用一個WKInterfaceController類函數即可:
[cpp] view plaincopy![]()
// WKInterfaceController
class func openParentApplication(userInfo: [NSObject: AnyObject],
reply: (([NSObject: AnyObject]!, NSError!) -> Void)?) -> Bool
// launches containing iOS application on the phone
// userInfo must be non-nil
但是,WatchKit卻并沒有實現幫助用戶打開iOS應用。當我在模擬器中進行測試時,它是能夠打開iOS應用的,但在真機環境下卻只能在后臺運行。盡管如此,它依然能快速傳遞信息并執行重要任務。
除上述之外,我還學會了另一個非常有用的事情:如何同時調試iOS和Watch版應用。在iOS應用指令中有一個可以接收WatchKit擴展信息的函數:
[cpp] view plaincopy![]()
// AppDelegate
func application(application: UIApplication, handleWatchKitExtensionRequest
userInfo: [NSObject: AnyObject]?,
reply: (([NSObject: AnyObject]!) -> Void)!)
當我次使用這個方法時并不奏效,而我也不知道該如何調試它。每次只能完成WatchKit或iOS端部署,而且還都是以iOS應用彈出警告結束,并且系統會嘗試調試代碼。后來我發現,有一個方法可以同時調試iOS和WatchKit App:
運行WatchKit App;
在你的模擬器中打開iOS版App;
返回Xcode;
選擇Debug> Attach to Process > (YOUR iOS App)
Brian Gilham——The Working Group高級移動開發者、Five Minute WatchKit博主
我犯過的大錯誤就是在iOS模擬器中單獨運行應用時很容易忘記其很多功能都是依賴于BTLE連接的。模擬器會嘗試通過延遲請求來解決這個問題,但有時它需要的回應時間實在太長。
因此,在對應用程序的設計和開發進行改進時,開發者可以問自己三個問題以自省:
如果這個視圖或操作需要長時響應該怎么辦?
如果根本得不到任何響應,應用程序會作何反應?
我有什么辦法可以解決這些問題?
對于這些問題,不同的應用會有不同的解決辦法,但有些事情非常值得考慮:
如果使用API響應或圖像超過一次的機會渺茫,就要盡可能地緩存。如果一個信息流無法做到每15分鐘更新一次,那就不要在每次啟動應用時運行API。
在用戶需要某些數據之前,就要利用任何機會去下載它,可以后臺獲取,并將其與緩存數據和已存在的數據相結合。
如果你不得不讓你的用戶等待應用啟動,可以考慮在這段加載的時間內播放些有趣的動畫,讓用戶覺得應用卡頓實屬大忌。同樣地,應該確保及時更新UI,讓用戶能了解到他的請求是否已經失敗。
Conrad Kramer——Workflow創始人
早前我們使用圖像選取器去處理問題,但它給人的感覺是,似乎要永遠加載下去,而且,內存的使用量會讓WatchKit擴展崩潰。在經過多次試驗和失敗后,我得出了以下幾點關于發送圖像到Apple Watch上的技巧:
圖片的縮略圖應適合屏幕的大小;
將圖片壓縮成JPEG或PNG格式;
調用-[WKInterfaceImage setImageData:],比使用UIImage對象更快,而且可以提高內存使用率。
如果需要使用動態圖片,可以使用+[UIImage animatedImageWithImages:duration:]。另外,Apple Watch不支持持續duration屬性,如需要,可使用-[WKInterfaceImage startAnimatingWithImagesInRange:duration:repeatCount:]。
James Robert——Media Predict CTO
我在開發Apple Watch應用時犯的個錯誤是嘗試把iPhone應用中的圖形元素直接搬運到Apple Watch上。終,我不得不重新考慮設計以讓應用在這個有限的環境中更完善。
正如前面Conrad所言,在開發Watch應用時需要更小心謹慎地使用圖像。用JPEG壓縮的NSData可以獲取到合適的圖像。但我只是將圖像分組進行替換,并對背景顏色和邊框進行設置。Watch的屏幕的太小,為了留出足夠的空間給文本必須要做出各種努力。
Curtis Herbert——獨立開發者&設計師
我在開發Watch版Slopes時犯了一個很大的錯誤,就是不能對視圖進行智能化更新。我會想能不能像iOS版那樣隨時更新屏幕,但事實卻無法讓人舒心,這些功能只能在藍牙開啟的情況下才能正常運轉。
在運行應用時,如果你注意到控制臺日志,就會發現WatchKit在試圖刪除那些它所認為的重復更新,而一些調用didDeactivate后的更新也會被忽視。蘋果十分積極地將更新發送至藍牙,并且耗能極小,但卻沒有為WKInterfaceController或WKView提供任何工具去追蹤這個狀況對用戶的影響。
Neil Kimmett——M&S Digital Labs開發者
我們在開發WatchKit App時犯的大錯誤就是關于各種文本元素周圍的邊距。在開發PC和手機端應用時,我們在屏幕邊緣和文本之間設置了一個非常漂亮并足夠大的間距,但在Watch上,如果使用黑色背景,那手表邊框就自然地和文本框之間產生了距離,所以從文本到屏幕邊緣的距離就是多余的了。
不設置間距,這在模擬器上看會有些奇怪,但在設備上就顯得非常自然。它還有一個額外的好處就是在有限的屏幕資源上可以有你更多的空余地方進行其他操作。
Kristina Thai——Intuit iOS軟件工程師
我犯的大錯誤之一是嘗試在reply dictionary中通過handleWatchKitExtensionRequest自定義類對象來向WatchKit擴展發送信息。當自定義對象輸入replyInfo dictionary時還是正常的,但它不能被plist文件序列化,所以會出現錯誤。如果你嘗試發送自定義對象,你將在后看到這樣一條提示錯誤的信息:
Error Domain=com.apple.watchkit.errors Code=2 "The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]" UserInfo=0x61000006f640 {NSLocalizedDescription=The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]}
因此,自定義對象不能通過plist文件序列化,也可以說iPhone上的應用在handleWatchKitExpensionRequest中調用reply(),即使你嘗試這樣做。在此,我列出一些可以在iPhone和Watch應用之間進行數據共享的方法:
你仍然可以使用reply dictionary去傳輸一些簡單的數據。初,為了可以在Apple Watch上顯示,我的自定義對象需要的是一段字符串,而這些通過應用是很容易傳遞的,狀態代碼和快速信息同樣如此。你也可以將稍微復雜一些的數據在App中用數組和字典等方式傳遞。
如果你需要自定義對象的所有屬性,首先設置App Groups,然后根據需求使用NSUserDefaults或NSFileManager。
以上兩條有一個非常有趣的共性就是使用NSKeyedArchiver將自定義對象存檔后,可以通過reply dictionary來進行傳輸。示例如下:
在手機端創建reply dictionary
[cpp] view plaincopy![]()
NSMutableDictionary *reply = [NSMutableDictionary new];
MyCustomObject *myObject = <something you need to send>;
reply[@"myKey"] = [NSKeyedArchiver archivedDataWithRootObject: myObject];
NSAttributedString *myString = <some attributed string>;
reply[@"otherKey"] = [NSKeyedArchiver archivedDataWithRootObject: myString];
解壓到Apple Watch端
[cpp] view plaincopy![]()
NSData *objectData = replyInfo[@"myKey"];
MyCustomObject *myObject = [NSKeyedUnarchiver unarchiveObjectWithData: objectData];
NSData *stringData = replyInfo[@"otherKey"];
NSAttributedString *myString = [NSKeyedUnarchiver unarchiveObjectWithData: stringData];
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。