iOS 8 CoreData iCloud 同步一致性问题

Trouble with iOS 8 CoreData iCloud sync consistency

我有一个使用 xCode 6.3.2 用 Swift 编写的通用应用程序。目前非常简单,因为当我按下一个按钮时,会生成一个随机数,然后使用 CoreData 进行存储。在我实施 iCloud 之前,这非常有效。启用 iCloud 后,存储新的随机数并不总是会传播到其他设备上。大多数时候都是这样,但并非总是如此。

我正在使用 iPad Air、iPhone 6 Plus 和 iPhone 4s

进行测试

我正在使用以下三个通知观察者:

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "persistentStoreDidChange", name: NSPersistentStoreCoordinatorStoresDidChangeNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "persistentStoreWillChange:", name: NSPersistentStoreCoordinatorStoresWillChangeNotification, object: managedContext.persistentStoreCoordinator)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "receiveiCloudChanges:", name: NSPersistentStoreDidImportUbiquitousContentChangesNotification, object: managedContext.persistentStoreCoordinator)

这是第三个函数:

func receiveiCloudChanges(notification: NSNotification)
{
    println("iCloud changes have occured")
    dispatch_async(dispatch_get_main_queue())
        {
            self.activityIndicator.startAnimating()
            self.updateLabel.text = "iCloud changes have occured"

            self.managedContext.performBlockAndWait
                { () -> Void in
                    self.managedContext.mergeChangesFromContextDidSaveNotification(notification)
                }
            self.reloadTextViewAndTableView()
            self.activityIndicator.stopAnimating()
        }
}

在 managedContext 完成合并之前,我不会尝试更新 UI,并且我正在主线程上执行所有操作。我真的很困惑为什么一台设备上的更改大约有 90-95% 的时间只显示在第二台或第三台设备上。

作为我试错的一部分,当我从我的测试设备上删除应用程序并重新安装时,有时会出现一条消息,提示 iCloud 操作正在等待,但我等待多长时间并不重要,一次设备不同步,它们保持这种状态。即使它们不同步,如果我添加另一个或两个数字,它们仍会传播到其他设备,但我总是会丢失更多数据。它似乎在大约 90% 的时间都有效。

我使用以下更新 UI:

func reloadTextViewAndTableView()
{
    let allPeopleFetch = NSFetchRequest(entityName: "Person")
    var error : NSError?
    let result = managedContext.executeFetchRequest(allPeopleFetch, error: &error) as! [Person]?

    //Now reload the  textView by grabbing every person in the DB and appending it to the textView
    textView.text = ""
    allPeople = managedContext.executeFetchRequest(allPeopleFetch, error: &error) as! [Person]
    for dude in allPeople
    {
        textView.text = textView.text.stringByAppendingString(dude.name)
    }
    tableView.reloadData()
    println("allPeople.count = \(allPeople.count)")
}

我真的在这里呆住了。我只是不确定为什么 "usually" 有效...

所以我仍然不确定 CoreData 有时如何或为什么会如上所述不同步。我发现,如果我非常快速地一个接一个地输入新数字,这通常会发生。

作为解决方法,我在 UI 中添加了一个按钮,允许用户通过使用以下选项重建 NSPersistentStore 来强制与 iCloud 重新同步。

NSPersistentStoreRebuildFromUbiquitousContentOption: true

我更希望商店始终与所有其他设备保持同步,但至少这样用户永远不会丢失数据。如果他们发现他们丢失了一条他们知道是在另一台设备上输入的记录,那么他们所要做的就是点击重新同步按钮。