在iOS迁移iCloud事务日志时查询核心数据时出现NSInternalInconsistencyException

时间:2015-09-30 16:57:18

标签: ios core-data icloud

在我的iOS应用程序中更新模型后,我开始在Crashlytics上看到此错误报告(轻量级迁移,因为数据存储通过iCloud同步)。这个问题似乎影响了2-3%的会议,我发现在测试环境中很难再现。

这是错误(崩溃线程的堆栈跟踪):

Thread : Crashed: com.twitter.crashlytics.ios.exception
0  webtv                          0x000000010031ad28 CLSProcessRecordAllThreads + 4298337576
1  webtv                          0x000000010031ad28 CLSProcessRecordAllThreads + 4298337576
2  webtv                          0x000000010031b1d8 CLSProcessRecordAllThreads + 4298338776
3  webtv                          0x0000000100305c08 CLSHandler + 4298251272
4  webtv                          0x0000000100318f20 __CLSExceptionRecord_block_invoke + 4298329888
5  libdispatch.dylib              0x00000001994c9770 _dispatch_client_callout + 16
6  libdispatch.dylib              0x00000001994d49c4 _dispatch_barrier_sync_f_invoke + 100
7  webtv                          0x0000000100318ab8 CLSExceptionRecord + 4298328760
8  webtv                          0x00000001003188d0 CLSExceptionRecordNSException + 4298328272
9  webtv                          0x0000000100318530 CLSTerminateHandler() + 4298327344
10 libc++abi.dylib                0x0000000198372f44 std::__terminate(void (*)()) + 16
11 libc++abi.dylib                0x0000000198372fd0 std::set_new_handler(void (*)()) + 90
12 libobjc.A.dylib                0x0000000198cdc1a4 _destroyAltHandlerList + 10
13 libdispatch.dylib              0x00000001994c9784 _dispatch_client_callout + 36
14 libdispatch.dylib              0x00000001994d49c4 _dispatch_barrier_sync_f_invoke + 100
15 CoreData                       0x0000000183e53b08 -[NSManagedObjectContext performBlockAndWait:] + 252
16 webtv                          0x00000001001320ec WTVCoreDataHelper.(executeSync in _B3CAA6076B08D24EA69CA58785DFF9DB)(NSFetchRequest, error : inout NSError?) -> [AnyObject]? (WTVCoreDataHelpers.swift:136)
17 webtv                          0x00000001001390f0 WTVCoreDataHelper.defaultProfile() -> WTVProfile? (WTVCoreDataHelpers.swift:529)
18 webtv                          0x00000001001335c0 WTVCoreDataHelper.(defaultProfileIfNil in _B3CAA6076B08D24EA69CA58785DFF9DB)(WTVProfile?) -> WTVProfile? (WTVCoreDataHelpers.swift:204)
19 webtv                          0x0000000100132de8 WTVCoreDataHelper.(systemFolder in _B3CAA6076B08D24EA69CA58785DFF9DB)(WTVProfile?) -> WTVFolder? (WTVCoreDataHelpers.swift:179)
20 webtv                          0x00000001001358a8 WTVCoreDataHelper.homePage(profile : WTVProfile?) -> WTVPage? (WTVCoreDataHelpers.swift:345)
21 webtv                          0x0000000100273bec SWWebBrowserViewController.homePageUrl.getter (SWWebBrowserViewController.swift:97)
22 webtv                          0x00000001002607f4 SWBrowserHomeButton.evaluateForChangeOfState(NSURL?) -> () (SWBrowserControlButtons.swift:94)
23 webtv                          0x000000010025e5b8 SWBrowserControlButton.store(FASFluxStore!, didEmitChangeNotification : NSNotification!) -> () (SWBrowserControlButtons.swift:36)
24 webtv                          0x000000010025e630 @objc SWBrowserControlButton.store(FASFluxStore!, didEmitChangeNotification : NSNotification!) -> () (SWBrowserControlButtons.swift)
[...]
49 GraphicsServices               0x000000018ef98088 GSEventRunModal + 180
50 UIKit                          0x00000001896caf60 UIApplicationMain + 204
51 webtv                          0x00000001002c0c60 main (AppDelegate.swift:19)
52 libdyld.dylib                  0x00000001994fa8b8 start + 4

...这是执行一些iCloud事务日志迁移的iOS线程

Thread : com.apple.coredata.ubiquity.entry.pq
0  libsystem_kernel.dylib         0x0000000199608c6c semaphore_wait_trap + 8
1  libdispatch.dylib              0x00000001994da684 _dispatch_semaphore_wait_slow + 244
2  Foundation                     0x00000001850fed94 -[NSFileCoordinator(NSPrivate) _blockOnAccessClaim:] + 380
3  Foundation                     0x00000001850ff8b0 -[NSFileCoordinator(NSPrivate) _coordinateReadingItemAtURL:options:error:byAccessor:] + 440
4  Foundation                     0x00000001850fd8fc -[NSFileCoordinator coordinateReadingItemAtURL:options:error:byAccessor:] + 72
5  CoreData                       0x0000000183f23280 -[PFUbiquityFileCoordinator coordinateReadingItemAtLocation:options:retryOnError:error:byAccessor:] + 140
6  CoreData                       0x0000000183f3c27c -[PFUbiquityLocation fileExistsAtLocationWithLocalPeerID:error:] + 324
7  CoreData                       0x0000000183f77790 -[PFUbiquitySafeSaveFile existsInCloud] + 88
8  CoreData                       0x0000000183f4b958 -[PFUbiquityMigrationManager migrateTransactionLogs:andBaselineIfNecessaryForStoreName:peerID:error:] + 1328
9  CoreData                       0x0000000183f5db18 -[PFUbiquitySetupAssistant initializeBaselineForStore:error:] + 2576
10 CoreData                       0x0000000183f5a3b4 -[PFUbiquitySetupAssistant finishSetupForStore:error:] + 2324
11 CoreData                       0x0000000183f59828 -[PFUbiquitySetupAssistant finishSetupWithRetry:] + 152
12 CoreData                       0x0000000183f222a8 __57-[PFUbiquitySwitchboardEntry executeBlockOnPrivateQueue:]_block_invoke + 64
13 libdispatch.dylib              0x00000001994c97b0 _dispatch_call_block_and_release + 24
14 libdispatch.dylib              0x00000001994c9770 _dispatch_client_callout + 16
15 libdispatch.dylib              0x00000001994d575c _dispatch_queue_drain + 864
16 libdispatch.dylib              0x00000001994cd274 _dispatch_queue_invoke + 464
17 libdispatch.dylib              0x00000001994c9770 _dispatch_client_callout + 16
18 libdispatch.dylib              0x00000001994d7bb0 _dispatch_root_queue_drain + 2140
19 libdispatch.dylib              0x00000001994d734c _dispatch_worker_thread3 + 112
20 libsystem_pthread.dylib        0x00000001996e9478 _pthread_wqthread + 1092
21 libsystem_pthread.dylib        0x00000001996e9028 start_wqthread + 4

我相信我的代码遵循核心数据并发的最佳实践(请参阅下面Swift代码的相关摘录)。特别是

  • managedObjectContext配置了PrivateQueueConcurrencyType
  • 对核心数据API的所有调用都包含在managedObjectContext.performBlock()
  • managedObjectContext已保存并在storeWillChange

    中重置

    我缺少什么?

以下是崩溃的代码

private func executeSync(request: NSFetchRequest) -> [AnyObject]? {        
    var results: [AnyObject]?
    if let moc = managedObjectContext {
      moc.performBlockAndWait({ () -> Void in
        do {
          try results = moc.executeFetchRequest(request) // Crashes here
        } catch let error as NSError {
          ERROR("ERROR executeFetchRequest of WTVCoreDataHelper threw an error \(error)")
        }
      })
    }
    return results
  }

设置persistentStoreCoordinatormanagedObjectContext

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
    var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("WebVideoCast.sqlite")
    var options = [NSObject:AnyObject]()
    options[NSPersistentStoreUbiquitousContentNameKey] = kConstants.ubiquityStoreIdentifier
    options[NSMigratePersistentStoresAutomaticallyOption] = true
    options[NSInferMappingModelAutomaticallyOption] = true
    var error: NSError? = nil
    var failureReason = "There was an error creating or loading the application's saved data."
    do {
      try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options)
    } catch var error as NSError {
      coordinator = nil
      var dict = [NSObject:AnyObject]()
      dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
      dict[NSLocalizedFailureReasonErrorKey] = failureReason
      dict[NSUnderlyingErrorKey] = error
      error = NSError(domain: kConstants.errorDomain, code: 9999, userInfo: dict)
      ERROR("Unresolved error \(error), \(error.userInfo)")
      abort()
    } catch {
      fatalError()
    }
    return coordinator
    }()

  lazy var managedObjectContext: NSManagedObjectContext? = {
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil {
      return nil
    }

    var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator
    // Set the MergePolicy to prioritise external inputs
    let mergePolicy = NSMergePolicy(mergeType:NSMergePolicyType.MergeByPropertyStoreTrumpMergePolicyType )
    managedObjectContext.mergePolicy = mergePolicy

    return managedObjectContext
    }()

相关代表方法:

@objc func storeWillChange(notification: NSNotification) {
    if let moc = self.managedObjectContext {
      moc.performBlockAndWait({ () -> Void in
        if moc.hasChanges {
          do {
            try moc.save()
          } catch let error as NSError {
            ERROR("ERROR Unresolved error while saving context \(error), \(error.userInfo)")
          } catch {
            fatalError()
          }
        }
        moc.reset()
      })
    }
  }

更新:我刚刚在模型更新到最新版本的设备上重现了一次 - 所以我真的不确定轻量级迁移是否是一个影响因素。

0 个答案:

没有答案