核心数据iCloud直到第二次启动才会填充tableview

时间:2015-05-06 02:02:57

标签: ios swift core-data

我创建了一个利用iCloud核心数据的应用。似乎我所有的困难部分都正常工作,但我错过了一些非常重要的东西。一旦安装在两个物理设备上,一个上的更改在第二个上显示为预期。问题是我必须安装应用程序,然后关闭它并在主数据视图中出现任何数据之前重新启动它。 Xcode 6.3.1 iOS 8.3

每个设备都是如此。从两台设备上删除应用程序后,我会在一台设备上安装该应用程序。我在控制台上收到了这个:

  

2015-05-04 15:33:05.297 BiopLogCloud [1353:734999]   -PFUbiquitySwitchboardEntryMetadata setUseLocalStorage :: CoreData:Ubiquity:   mobile~C1432E0B-D885-418C-996C-5E6CDD45D7F1:BiopLogCloudStore使用   本地存储:1在persistentStoreDidChange里面的count是0   persistentStoreDidChange里面的persistentStoreDidChange   persistentStoreDidChange里面的persistentStoreDidChange   persistentStoreDidChange里面的persistentStoreDidChange   persistentStoreDillChange中的persistentStoreWillChange 2015-05-04   15:33:06.979 BiopLogCloud [1353:735018]   -PFUbiquitySwitchboardEntryMetadata setUseLocalStorage :: CoreData:Ubiquity:   mobile~C1432E0B-D885-418C-996C-5E6CDD45D7F1:BiopLogCloudStore使用   本地存储:0

注意count变量 - 为零。然后我重新启动应用程序和 数据存在。无论我是从Xcode构建还是运行都没关系 或者只是从设备启动应用程序。数据立即显示 如果从Xcode启动,我在控制台中收到以下内容:

  

2015-05-04 15:35:03.542 BiopLogCloud [1358:735588]   -PFUbiquitySwitchboardEntryMetadata setUseLocalStorage :: CoreData:Ubiquity:   mobile~C1432E0B-D885-418C-996C-5E6CDD45D7F1:BiopLogCloudStore使用   本地存储:1 persistentStoreDidChange内的计数为12   2015-05-04 15:35:04.062 BiopLogCloud [1358:735625]   -PFUbiquitySwitchboardEntryMetadata setUseLocalStorage :: CoreData:Ubiquity:   mobile~C1432E0B-D885-418C-996C-5E6CDD45D7F1:BiopLogCloudStore使用   本地存储:0

在第二台设备上重复相同的过程后,应用程序按预期工作。

由于它在这个初始问题之后起作用,我不确定要显示的代码,但这里是相关的持久存储和获取的结果代码:

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {

    var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

    let documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).last as! NSURL

    let storeURL = documentsDirectory.URLByAppendingPathComponent("BiopLogCloud.sqlite")

    //if the store is incompatible
    //NSFileManager.defaultManager().removeItemAtURL(url, error: nil)
    //nuke it

    var error: NSError? = nil
    var failureReason = "There was an error creating or loading the application's saved data."

    let storeOptions = [NSPersistentStoreUbiquitousContentNameKey : "BiopLogCloudStore"]

    if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: storeOptions, error: &error) == nil {
        coordinator = nil
        // Report any error we got.
        let dict = NSMutableDictionary()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data - cloud persistent store not created"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason
        dict[NSUnderlyingErrorKey] = error
        error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict as [NSObject : AnyObject])
        // Remember to create an alert for the user in case of error
        NSLog("Unresolved error \(error), \(error!.userInfo)")
        abort()
    }

    return coordinator
}()

lazy var managedObjectContext: NSManagedObjectContext? = {

    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil {
        println("YES! You have found the issue - coordinator is nil")
        return nil 
    }

    var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator

    return managedObjectContext
}()

var fetchedResultsController: NSFetchedResultsController {

    if myFetchedResultsController != nil {
        return myFetchedResultsController!
    }

    let fetchRequest = NSFetchRequest()

    // Edit the entity name as appropriate auto generate didn't work - fix that
    let entity = NSEntityDescription.entityForName("Patient", inManagedObjectContext: managedObjectContext)

    fetchRequest.entity = entity

    // Set the batch size to a suitable number.
    fetchRequest.fetchBatchSize = 50

    // Edit the sort keys as appropriate.
    let sortDescriptor = NSSortDescriptor(key: "dateEntered", ascending: false)
    let sortDescriptors = [sortDescriptor]

    fetchRequest.sortDescriptors = [sortDescriptor]

    let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: "PatientCache")

    var countError : NSError? = nil
    var count = managedObjectContext.countForFetchRequest(fetchRequest, error: &countError)
    println("The count is \(count)")

    aFetchedResultsController.delegate = self
    myFetchedResultsController = aFetchedResultsController

    var error: NSError? = nil
    if !myFetchedResultsController!.performFetch(&error) {
         // Replace this implementation with code to handle the error appropriately.

         println("Unresolved error \(error), \(error!.userInfo)")
         abort()
    }

    return myFetchedResultsController!
}    
var myFetchedResultsController: NSFetchedResultsController? = nil

2 个答案:

答案 0 :(得分:0)

一种情况是,您在收到NSPersistentStoreDidImportUbiquitousContentChangesNotification时没有收听或未更新表格视图。该通知是您如何知道新数据来自iCloud的。如果您没有正确处理它,您的应用将不会显示任何新数据,直到您强制它重新加载其数据 - 例如通过终止应用并重新启动它。

答案 1 :(得分:0)

我在这个问题上挣扎了很长时间。似乎在本地创建过程中的某个地方,表视图控制器认为它与数据有良好的连接,但事实并非如此。

如果您使用标准xcode应用程序进行tableview,取得结果控制器和icloud,我发现我需要做的就是在商店更改时将一些代码放在通知中心调用的函数中。

xcode设置了一个帮手fetchedResultsController

var _fetchedResultsController: NSFetchedResultsController? = nil

如果你将它设置为nil,那么调用fetchedResultsController的重新创建就应该很好。同样,我使用的是带有修改的标准变量frc:

var fetchedResultsController: NSFetchedResultsController {
    if _fetchedResultsController != nil {
        return _fetchedResultsController!
    }

    ...bunch more code
}

所以在我命名为handleStoresDidChange(..)的函数中,没有frc并重新创建它

func handleStoresDidChange(notification : NSNotification) {

    print("storesDidChange notification:\(notification)")
    self.view.userInteractionEnabled = true

    _fetchedResultsController = nil
    self.fetchedResultsController
    tableView.reloadData()

}//handleStoresDidChange

希望对你有用。