首页 > 网站 > 建站经验 > 正文

A!pp与Extensions间通信共享数据

2019-11-02 14:53:35
字体:
来源:转载
供稿:网友

   最近玩了玩Watch开发,而目前Watch的主要逻辑处理都是放在WatchKit Extension。真正的Host App,也就是WatchKit App只是用来在界面上显示数据的。于是实践了下containing app与app extension之间的通信和数据共享。

  App Groups & Framework

  这两样兵器大家都很熟悉。想要共享数据就需要开启App Groups,给group起一个风骚的名字,这样无论是NSUserDefaults还是NSFileMana

动态图片[www.62-6.com]
ger都能通过App Groups共享持久层数据了。Core Data也需要NSFileManager提供存储的URL支持,而存取Core Data中的数据需要大量的模板代码,在持久层文件共享之后,代码也应该做到共享,所以将能够重用的代码打包成Framework就显得尤为重要。(除非是为了做毕设凑代码量)

  还是以HardChoice为例,我新建了一个类型为Cocoa Touch Framework的target,名字叫DataKit。新建一个DataAccess.swift文件并将以前AppDelegate.swift中自动生成的Core Data模版代码转移过来。得益于Swift1.2的改进,构造一个线程安全的单例模式变得无比简单:

  private static let instance = DataAccess()

  public class var sharedInstance : DataAccess {

  return instance

  }

  需要注意Swift的权限控制问题,我们需要在暴漏给框架使用者的公开接口和属性前加上public关键字修饰。

  为了实现Core Data持久层共享,需要修改原先的applicationDocumentsDirectory属性:

  lazy var applicationDocumentsDirectory: NSURL = {

  // The directory the application uses to store the Core Data store file. This code uses a directory named "com.yxy.iCloudCoreDataTest" in the application's documents Application Support directory.

  // let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)

  // return urls[urls.count-1] as! NSURL

  var sharedContainerURL:NSURL? = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier(appGroupIdentifier)

  return sharedContainerURL ?? NSURL()

  }()

  在这里containerURLForSecurityApplicationGroupIdentifier方法起到了至关作用。

  同样能够共享的代码就是Model层,它们都是NSManagedObject的子类,用于存储Core Data中的数据实例。在把它们从原来的位置拖拽过来时别忘了更改下文件的target:”File inspector”->”Target Membership”,选中DataKit。

  在处理iCloud与Core Data同步数据时,我对NSPersistentStoreCoordinatorStoresWillChangeNotification、NSPersistentStoreCoordinatorStoresDidChangeNotification和NSPersistentStoreDidImportUbiquitousContentChangesNotification这三个数据更新的通知进行了观察和处理,但是写在了persistentStoreCoordinator计算属性的get方法中。现在使用lazy关键字进行惰性加载,导致对这三个数据更新通知的观察延后,这会引发严重的错误。所以需要将那三个addObserverForName(name, object, queue, usingBlock)方法挪到init()方法中,在第一时间观察通知。

  最后在AppDelegate.swift中添加import DataKit,替换掉中的application(application, didFinishLaunchingWithOptions) -> Bool方法中controller.managedObjectContext = managedObjectContext为controller.managedObjectContext = DataAccess.sharedInstance.managedObjectContext,也就是不再使用以前的模板代码中的上下文实例,而是用DataAccess单例中的managedObjectContext。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表