Swift Ensembles 设置和 ubiquityContainerIdentifier

Posted

技术标签:

【中文标题】Swift Ensembles 设置和 ubiquityContainerIdentifier【英文标题】:Swift Ensembles Set Up & ubiquityContainerIdentifier 【发布时间】:2015-10-18 22:48:52 【问题描述】:

书上说,

“集成标识符用于匹配跨设备的商店。这是 重要的是这对于整体中的每个商店都是相同的。”

let ensembleFileSystem = CDEICloudFileSystem(ubiquityContainerIdentifier: "???")

这是否需要对所有用户都是唯一的?还是仅用于我的应用程序?

如果有人有关于如何设置 Ensembles 的 Swift 版本,那就太好了。

到目前为止,我所需要的就这些了吗?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 

    let ensembleFileSystem = CDEICloudFileSystem(ubiquityContainerIdentifier: "???")

    let modelURL = NSBundle.mainBundle().URLForResource("DataModel", withExtension: "momd")!
    let url = applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")

    let ensemble = CDEPersistentStoreEnsemble(ensembleIdentifier: "mainstore", persistentStoreURL: url, managedObjectModelURL: modelURL, cloudFileSystem: ensembleFileSystem!)


    if !ensemble.leeched 
        ensemble.leechPersistentStoreWithCompletion  (error) -> Void in
            if error != nil 
                print("cannot leech")
                print(error!.localizedDescription)
            
        
    

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "syncWithCompletion:", name: CDEMonitoredManagedObjectContextDidSaveNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "syncWithCompletion:", name: CDEICloudFileSystemDidDownloadFilesNotification, object: nil)

    return true


func syncWithCompletion(notification:NSNotification) 
    print("synced \(notification)")
    managedObjectContext.mergeChangesFromContextDidSaveNotification(notification)

有些东西丢失了我得到这个错误日志

User is not logged into iCloud

尽管登录很明显

print(NSFileManager.defaultManager().ubiquityIdentityToken)

不是零

【问题讨论】:

【参考方案1】:

最终成功了 - 在 1.0 Git 中找到示例应用

我相信我是在快速获取 - 没有给设置过程足够的时间来完成。

支持这个框架 - 如果你喜欢第 1 版,请购买 ensembles 2。

更新..更简单的方法

我只是使用苹果提供的普通核心数据栈。

这是使合奏发挥作用的附加功能。

var ensemble:CDEPersistentStoreEnsemble!

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 

    let file = CDEICloudFileSystem(ubiquityContainerIdentifier: nil)
    let modelURL = NSBundle.mainBundle().URLForResource("DataModel", withExtension: "momd")!
    let storeurl = self.applicationDocumentsDirectory.URLByAppendingPathComponent("store.sqlite")
    ensemble = CDEPersistentStoreEnsemble(ensembleIdentifier: "MyStoreName", persistentStoreURL: storeurl, managedObjectModelURL: modelURL, cloudFileSystem: file)
    ensemble.delegate = self

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "localSaveOccurred:", name: CDEMonitoredManagedObjectContextDidSaveNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "cloudDataDidDownload:", name: CDEICloudFileSystemDidDownloadFilesNotification, object: nil)

    syncWithCompletion  completed in
        if completed 
            print("SUCCESSS")
        
        else 
            print("FAIL")
        
    

    return true


// MARK: - Sync

func applicationDidEnterBackground(application: UIApplication) 
    print("Did Enter Background Save from App Delegate")

    let identifier = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler(nil)
    saveContext()

    syncWithCompletion  (completed) -> Void in
        if completed 
            UIApplication.sharedApplication().endBackgroundTask(identifier)
        
    


func applicationWillEnterForeground(application: UIApplication) 
    syncWithCompletion  (completed) -> Void in

    


func localSaveOccurred(note:NSNotification) 
    syncWithCompletion  (completed) -> Void in

    


func cloudDataDidDownload(note:NSNotification) 
    syncWithCompletion  (completed) -> Void in
        print("items from iCloud arrived")
    


func syncWithCompletion(completion:(completed:Bool) -> Void) 

    UIApplication.sharedApplication().networkActivityIndicatorVisible = true

    if !ensemble.leeched 
        ensemble.leechPersistentStoreWithCompletion(nil)
    
    else 
        ensemble.mergeWithCompletion error in
            if error != nil 
                print("cannot merge \(error!.localizedDescription)")
                UIApplication.sharedApplication().networkActivityIndicatorVisible = false
                completion(completed: false)
            
            else 
                print("merged")
                UIApplication.sharedApplication().networkActivityIndicatorVisible = false
                completion(completed: true)
            
        
    


// MARK: - Ensemble Delegate Methods

func persistentStoreEnsemble(ensemble: CDEPersistentStoreEnsemble!, didSaveMergeChangesWithNotification notification: NSNotification!) 

    managedObjectContext.performBlockAndWait  () -> Void in
        self.managedObjectContext.mergeChangesFromContextDidSaveNotification(notification)
    


func persistentStoreEnsemble(ensemble: CDEPersistentStoreEnsemble!, globalIdentifiersForManagedObjects objects: [AnyObject]!) -> [AnyObject]! 
    return (objects as NSArray).valueForKeyPath("uniqueIdentifier") as! [AnyObject]

我的第一条路

这里是 Swift,还有一些附加功能

var ensemble:CDEPersistentStoreEnsemble!
var cloudFileSystem:CDEICloudFileSystem!
var managedObjectContext: NSManagedObjectContext!

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
    // Override point for customization after application launch.

    setUpCoreData()

    let modelURL = NSBundle.mainBundle().URLForResource("YourDataModel", withExtension: "momd")!
    cloudFileSystem = CDEICloudFileSystem(ubiquityContainerIdentifier:"USE_YOUR_APPS_REVERSE DOMAIN NAME HERE")

来自开发者:RE ubiquityContainerIdentifier

这不是 Ensembles 本身的一部分。它来自 iCloud。每个应用程序 使用 iCloud 必须有一个无处不在的容器 ID。你可以在 启用 iCloud 时的应用设置。每个应用程序都是独一无二的,我们 仅当您选择 iCloud(例如不是 Dropbox)时才使用它。

    ensemble = CDEPersistentStoreEnsemble(ensembleIdentifier: "store", persistentStoreURL: storeURL(), managedObjectModelURL: modelURL, cloudFileSystem: cloudFileSystem!)
    ensemble.delegate = self

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "localSaveOccurred:", name: CDEMonitoredManagedObjectContextDidSaveNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "cloudDataDidDownload:", name: CDEICloudFileSystemDidDownloadFilesNotification, object: nil)

    syncWithCompletion  completed in
        if completed 
            print("SUCCESSS")
        
        else 
            print("FAIL")
        
    

    return true


// MARK: - Core Data Stack

func setUpCoreData() 

    let modelURL = NSBundle.mainBundle().URLForResource("DataModel", withExtension: "momd")!
    guard let model = NSManagedObjectModel(contentsOfURL: modelURL) else  fatalError("cannot use model") 

    do 
        try NSFileManager.defaultManager().createDirectoryAtURL(storeDirectoryURL(), withIntermediateDirectories: true, attributes: nil)
    
    catch 
        fatalError("cannot create dir")
    

    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
    //NSDictionary *options = @NSMigratePersistentStoresAutomaticallyOption: @YES, NSInferMappingModelAutomaticallyOption: @YES;

    let failureReason = "There was an error creating or loading the application's saved data."

    do 
        try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL(), options: nil)

        managedObjectContext = NSManagedObjectContext.init(concurrencyType: .MainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

     catch 
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason

        dict[NSUnderlyingErrorKey] = error as NSError
        let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        // Replace this with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
        abort()
    


func storeDirectoryURL() -> NSURL 

    let directoryURL = try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
    return directoryURL


func storeURL() -> NSURL 
    let url = storeDirectoryURL().URLByAppendingPathComponent("store.sqlite")
    return url



// MARK: - Sync

func applicationDidEnterBackground(application: UIApplication) 
    print("Did Enter Background Save from App Delegate")

    let identifier = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler(nil)
    saveContext()

    syncWithCompletion  (completed) -> Void in
        if completed 
            UIApplication.sharedApplication().endBackgroundTask(identifier)
        
    


func applicationWillEnterForeground(application: UIApplication) 
    syncWithCompletion  (completed) -> Void in

    


func localSaveOccurred(note:NSNotification) 
    syncWithCompletion  (completed) -> Void in

    


func cloudDataDidDownload(note:NSNotification) 
    syncWithCompletion  (completed) -> Void in

    


func syncWithCompletion(completion:(completed:Bool) -> Void) 

    if !ensemble.leeched 
        ensemble.leechPersistentStoreWithCompletion  error in
            if error != nil 
                print("cannot leech \(error!.localizedDescription)")
                completion(completed: false)
            
            else 
                print("leached!!")
                completion(completed: true)
            
        
    
    else 
        ensemble.mergeWithCompletion error in
            if error != nil 
                print("cannot merge \(error!.localizedDescription)")
                completion(completed: false)
            
            else 
                print("merged!!")
                completion(completed: true)
            
        
    


// MARK: - Ensemble Delegate Methods

func persistentStoreEnsemble(ensemble: CDEPersistentStoreEnsemble!, didSaveMergeChangesWithNotification notification: NSNotification!) 

    print("did merge changes with note")


    managedObjectContext.mergeChangesFromContextDidSaveNotification(notification)


func persistentStoreEnsemble(ensemble: CDEPersistentStoreEnsemble!, globalIdentifiersForManagedObjects objects: [AnyObject]!) -> [AnyObject]! 
    return (objects as NSArray).valueForKeyPath("uniqueIdentifier") as! [AnyObject]

【讨论】:

对你有好处!您应该提供它为什么不起作用的详细信息,以及为什么它在您以前没有的情况下起作用……然后接受它作为答案。 感谢 Jody 推荐合奏.. 效果很好。没有更多的 iCloud 头痛。该应用程序只是同步,并且同步良好。

以上是关于Swift Ensembles 设置和 ubiquityContainerIdentifier的主要内容,如果未能解决你的问题,请参考以下文章

iOS Swift 中的合奏

在使用 Ensembles 进行 CoreData 和 iCloud 同步之前,我是不是需要任何 iCloud 设置?

Core Data 与 Ensembles 的 iCloud 同步

将 Ensembles 添加到现有 Coredata / iCloud 应用程序的步骤

iCloud 和配置文件中缺少 ubiquity-kvstore-identifier

Apple_Ubiquity_Message 到底是啥?