|
|
51CTO旗下网站
|
|
移动端

iOS App与WatchKit Extension的数据通信

NSUserDefaults是快速共享信息的途径。它适合存储各种快速访问和计算的小型数据,比如用户名与档案信息。如果希望使用UserDefaults,请用于静态数据这样用户不必考虑数值的变化。

作者:来源:艾佢K的博客|2015-06-30 10:48

NSUserDefaults

NSUserDefaults是快速共享信息的途径。它适合存储各种快速访问和计算的小型数据,比如用户名与档案信息。如果希望使用UserDefaults,请用于静态数据这样用户不必考虑数值的变化。

你需要设定App Group来让设备通过共享容器来实现数据共享,确保手表扩展和ios target都已如此设置。基本上就是针对两个设备创建一个统一的App Group标识符。如果需要删除它,可以以类似的方法进行。

你可以通过之前创建的App Group名来使用defaults,基本上就是为特定的key键值设置对象。在iPhone上,用户输入了文本,保存,文本就存到了应用共享的UserDefaults里。在Watch上,你可以从AppGroup得到defaults然后进行手表显示内容的更新。

  1. // on the iPhone app 
  2. letdefaults=NSUserDefaults(suiteName:"group.com.natashatherobot.userdefaults"
  3. letkey="userInput" 
  4.  
  5. overridefuncviewDidLoad(){ 
  6. super.viewDidLoad() 
  7. textLabel.text=defaults?.stringForKey(key)??"Type Something..." 
  8. @IBActionfunconSaveTap(sender:AnyObject){ 
  9.  
  10. letsharedText=textField.text 
  11.  
  12. textLabel.text=sharedText 
  13.  
  14. defaults?.setObject(sharedText,forKey:key) 
  15. defaults?.synchronize() 
  16. // WatchKit 
  17. classInterfaceController:WKInterfaceController{ 
  18. @IBOutletweakvartextLabel:WKInterfaceLabel! 
  19.  
  20. letdefaults=NSUserDefaults(suiteName: 
  21. "group.com.natashatherobot.userdefaults"
  22.  
  23. varuserInput:String?{ 
  24. defaults?.synchronize() 
  25. returndefaults?.stringForKey("userInput"

NSFileCoordinator

对更大型的数据来说,NSFileCoordinator是管理应用和watch扩展的共享空间里文件的方式之一。对于有限列表的内容它很合适,同时也适用于图像文件。

下面的例子是个简单的代办事项列表app,在手机上增加任务然后暑假传输到WatchKit扩展并在手表上显示。你的视图控制器需要遵循NSFilePresenter协议,除了实现两个必需方法,其它不是很关键。FilePresenter协议有一个item URL,就是填你的AppGroup标识符的地方。通过URL,你在对应目录建立一个文件。有必要的话你也可以通过操作队列来控制多线程访问。

另外,presentedItemDidChange这个代理方法,在FilePresenter里通知你是否一个对象发生了改变,来让你更新app数据而无需用户手动刷新。

然而这里还是有个关于NSFileCoordinator与NSFilePresenter 的bug而不方便在扩展里使用。具体可参见Natasha的网站。

在代办事项数组里利用FileCoordinator写入一个文件,可以通过读写文件以实现打包和解包事项的数据到事项数组,接下来可以依据文件里的事项数据计算生成表格。需要注意的是如果你设计了删除功能,而watch扩展和iPhone应用都能修改文件,会遇到线程同步的麻烦。

  1. // iPhone app 
  2. privatefuncsaveTodoItem(todoItem:String){ 
  3.  
  4. // write item into the todo items array 
  5. ifletpresentedItemURL=presentedItemURL{ 
  6.  
  7. fileCoordinator.coordinateWritingItemAtURL(presentedItemURL,options:nil,error:nil) 
  8. {[unownedself](newURL)->Voidin 
  9.  
  10. self.todoItems.insert(todoItem,atIndex:0
  11.  
  12. letdataToSave=NSKeyedArchiver.archivedDataWithRootObject(self.todoItems) 
  13. letsuccess=dataToSave.writeToURL(newURL,atomically:true
  14. // in the Watch 
  15. // MARK: Populate Table From File Coordinator 
  16.  
  17. privatefuncfetchTodoItems(){ 
  18.  
  19. letfileCoordinator=NSFileCoordinator() 
  20.  
  21. ifletpresentedItemURL=presentedItemURL{ 
  22.  
  23. fileCoordinator.coordinateReadingItemAtURL(presentedItemURL,options:nil,error:nil) 
  24. {[unownedself](newURL)->Voidin 
  25.  
  26. ifletsavedData=NSData(contentsOfURL:newURL){ 
  27. self.todoItems=NSKeyedUnarchiver.unarchiveObjectWithData(savedData)as[String] 
  28. self.populateTableWithTodoItems(self.todoItems) 

Frameworks

“If the code appears more than once, it probably belongs in a framework.(如果代码出现超过一次,应该考虑能否放到框架里)”

-WWDC 2014, Building Modern Frameworks

框架对于业务逻辑、CoreData、可重用UI组件来说很棒。就像WWDC里说的那样,你可以将重复代码放到框架里。在FileCoordinator的例子里,我们获取和读写文件的代码出现了两次,可以把它们提取到一个framework框架里。建立框架很简单:建立新target,选择Cocoa Touch framework,然后命名。它会在你的iOS应用里自动链接,因此也不要忘了在WatchKit扩展里进行链接。

关键的一点,特别是对于Swift语言来说,应该把框架认作一个API。它需要声明为公共的(public),因为这是iOS应用和watchkit扩展共用的接口。因此如果你在建立对象类,确保public关键字也加上了。这样在手机和手表应用里你导入了框架就可以访问任何公共内容。

  1. importWatchKit 
  2. importMySharedDataLayer 
  3. classInterfaceController:WKInterfaceController{ 
  4. @IBOutletweakvarfavoriteThingsLabel:WKInterfaceLabel! 
  5.  
  6. overridefuncawakeWithContext(context:AnyObject?){ 
  7. super.awakeWithContext(context) 
  8.  
  9. letmyFavoriteThings=MySharedData().myFavoriteThings 
  10.  
  11. letfavoriteThingsString=", ".join(myFavoriteThings) 
  12. favoriteThingsLabel.setText("My favorite things are \(favoriteThingsString)"

Keychain Sharing

钥匙链共享是针对更高安全性要求的数据的。UserDefaults提供的安全性不满足时,你可以用钥匙链共享来保障信息安全及跨扩展的共享能力。

WatchKit目前的一个大问题是没有认证机制。苹果提供了KeychainIteamWrapper的示例,但API太老不支持ARC。我推荐使用这个版本https://gist.github.com/dhoerl/1170641,它基于ARC并有清晰的接口。

根据问题是如何通过access group初始化KeychainItemWrapper。与AppGroup的概念类似,设备之间有共享空间。你在iOS和WatchKit扩展中都需要钥匙链来访问用户数据。通过键值存储体系,你设定用户名和密码并用同一个标识符建立同一类型的keychain项。这个例子里仅展示了当用户填好用户名密码时WatchKit扩展展示数据的这一工作过程。

  1. // iPhone app 
  2. @IBActionfunconSaveTap(sender:AnyObject){ 
  3.  
  4. letusername=usernameTextField.text 
  5. letpassword=passwordTextField.text 
  6.  
  7. letkeychainItem=KeychainItemWrapper(identifier:"SharingViaKeychain",accessGroup:"W6GNU64U6Q.com.natashatherobot.SharingViaKeychain"
  8.  
  9. // WatchKit extension 
  10. letkeychainItem=KeychainItemWrapper(identifier:"SharingViaKeychain",accessGroup:"W6GNU64U6Q.com.natashatherobot.SharingViaKeychain"
  11.  
  12.  
  13. letpasswordData=keychainItem.objectForKey(kSecValueData)asNSData 
  14. letpassword=NSString(data:passwordData,encoding:NSUTF8StringEncoding) 
  15.  
  16. letusername=keychainItem.objectForKey(kSecAttrAccount)as?String 

【编辑推荐】

  1. App变现从0到1:懂用户才能盘活
  2. 11个超棒的iOS开发学习网站
  3. iOS UIWebView URL拦截
【责任编辑:chenqingxiang TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

Cisco网络工程案例精粹

《Cisco网络工程案例精粹》是一本以案例为基础兼顾知识概述的案例性书籍,所收录的案例都是笔者精心挑选出来的在网络工作中常见的案例。 ...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊