【问题标题】:Core Data iCloud does not populate tableview until second launchCore Data iCloud 在第二次启动之前不会填充 tableview
【发布时间】:2015-05-06 02:02:57
【问题描述】:

我创建了一个将 Core Data 与 iCloud 结合使用的应用程序。似乎我所有困难的部分都能正常工作,但缺少一些非常重要的东西。一旦安装在两台物理设备上,其中一台的更改会按预期显示在第二台上。问题是我必须安装应用程序,然后在任何数据出现在主表视图中之前关闭它并重新启动它。 Xcode 6.3.1 iOS 8.3

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

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

注意计数变量 - 为零。然后我重新启动应用程序和 数据存在。我是否从 Xcode 构建和运行都没有关系 或者只是从设备启动应用程序。数据即刻出现 如果从 Xcode 启动,我会在控制台中收到以下信息:

2015-05-04 15:35:03.542 BiopLogCloud[1358:735588] -PFUbiquitySwitchboardEntryMetadata setUseLocalStorage::CoreData:Ubiquity: 手机~C1432E0B-D885-418C-996C-5E6CDD45D7F1:BiopLogCloudStore 使用 本地存储:1persistentStoreDidChange 内的计数为 12 2015-05-04 15:35:04.062 BiopLogCloud [1358:735625] -PFUbiquitySwitchboardEntryMetadata setUseLocalStorage::CoreData:Ubiquity: 手机~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

【问题讨论】:

    标签: ios swift core-data


    【解决方案1】:

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

    【讨论】:

    • 我确实在监听这个通知(在 viewWillAppear 中)并处理它,包括重新加载 tableview。一旦应用程序“启动并运行”,更改就会持续存在并在设备之间传输。只有在初始加载时,主表视图中才会显示任何数据。在初始安装中必须有一些不同的处理方式。重新启动后,应用按预期运行。
    【解决方案2】:

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

    如果您使用标准的 xcode 应用程序进行 tableview、fetched results controller 和 icloud,我发现我需要做的就是在商店更改时通知中心调用的函数中放置一些代码。

    xcode 设置一个帮助器 fetchedResultsController

    var _fetchedResultsController: NSFetchedResultsController? = nil
    

    如果您将其设置为 nil,则调用 fetchedResultsController 重新创建您应该很高兴。同样,我使用的是经过修改的标准变量 frc:

    var fetchedResultsController: NSFetchedResultsController {
        if _fetchedResultsController != nil {
            return _fetchedResultsController!
        }
    
        ...bunch more code
    }
    

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

    func handleStoresDidChange(notification : NSNotification) {
    
        print("storesDidChange notification:\(notification)")
        self.view.userInteractionEnabled = true
    
        _fetchedResultsController = nil
        self.fetchedResultsController
        tableView.reloadData()
    
    }//handleStoresDidChange
    

    希望对你有用。

    【讨论】:

      猜你喜欢
      • 2012-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-25
      • 2012-02-27
      • 2015-04-09
      • 2014-06-14
      相关资源
      最近更新 更多