2014-10-07 28 views
2

虽然我的一个NSManagedObjectContext正在运行其performBlock用户已选择退出其帐户(这将重置所有上下文和删除持久性存储)。该复位代码显然是被在相似的时间为performBlock运行,因此应用程序崩溃与例外:iOS 8应用程序崩溃时重置我的NSManagedObjectContext,而在performBlock

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator'

它崩溃的准确位置似乎是当一个上下文在其performBlock扑救,然后它会发出did save通知,并合并到其他上下文中。这里是堆栈跟踪:

0 CoreFoundation      0x03b96df6 __exceptionPreprocess + 182 

1 libobjc.A.dylib      0x03820a97 objc_exception_throw + 44 

2 CoreData       0x034f7791 _PFRetainedObjectIDCore + 1169 

3 CoreData       0x034f72f0 -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:] + 32 

4 CoreData       0x034db0f3 -[NSManagedObjectContext objectWithID:] + 595 

5 CoreData       0x0352e14e _faultBatchAtIndex + 1102 

6 CoreData       0x0352ed02 -[_PFBatchFaultingArray objectAtIndex:] + 50 

7 CoreData       0x035dd010 +[NSFetchedResultsController(PrivateMethods) _insertIndexForObject:inArray:lowIdx:highIdx:sortDescriptors:] + 144 

8 CoreData       0x035d7ba2 -[NSFetchedResultsController(PrivateMethods) _postprocessInsertedObjects:] + 738 

9 CoreData       0x035da3dd __77-[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:]_block_invoke + 2285 

10 CoreData       0x034e7454 developerSubmittedBlockToNSManagedObjectContextPerform + 196 

11 CoreData       0x034e7337 -[NSManagedObjectContext performBlockAndWait:] + 231 

12 CoreData       0x035d9acf -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 127 

13 Foundation       0x00eff929 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40 

14 CoreFoundation      0x03b61974 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20 

15 CoreFoundation      0x03a4f61b _CFXNotificationPost + 3051 

16 Foundation       0x00eeef26 -[NSNotificationCenter postNotificationName:object:userInfo:] + 98 

17 CoreData       0x034c84d3 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 83 

18 CoreData       0x034d9cbe -[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] + 3934 

19 CoreData       0x034d8d40 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 496 

20 App        0x00319707 __57-[ContextManager contextDidSavePrivateQueueContext:]_block_invoke + 103 

这是仅iOS 8 - iOS 7正常工作。我无法弄清楚的是,如果这是iOS 8的一个错误,我感受到了影响,或者Apple已经将“新功能”引入了Core Data中,这已经打破了我们的重置流程。任何人都可以对此有所了解吗?

+0

“我的一个NSManagedObjectContext”。这似乎表明你有不止一个。他们是亲子还是同龄人? – quellish 2014-10-08 14:59:05

+0

一个是私人的,一个是主要的。没有父母/子女。 – Harry 2014-10-08 15:32:01

+0

如果你正在使用队列封闭,你应该使用亲子,否则你会看到像这样的问题。 – quellish 2014-10-08 15:41:56

回答

1

我通过NSManagedObjectContext添加类别和使用objc_setAssociatedObject魔法把一个标志固定的bug。该标志是用于执行任何执行块的上下文是否安全。为此,我在名为safePerformBlock的类别中添加了另一种方法,该类别查看该标志。如果是假的,我立即返回了,而不是处理中传递块。

当我删除上下文的持久性存储,该标志设置为不安全。当用户重新登录并重新创建持久性存储时,该标志被设置为安全。

本质上讲,我对上下文的performBlocks取消令牌处理此标志。为什么API中没有这个我不知道的东西。在这种情况下,这是我能找到的最佳解决方案。

0

核心数据不是线程安全的。一个NSManagedObjectContext只能在创建它的线程中使用。一旦持久性商店消失,就不能使用它。 iOS 8中的时机很有可能会有所不同,但由于您无法依赖时机,因此它可能总是您代码中的一个错误。

+0

正如海报指出的那样,他正在使用带有performBlock的队列限制,它可以安全地从任何线程调用。 – quellish 2014-10-08 14:59:36

0

你可以把复位操作在同一个线程比你performBlock,把队列中“无conccurency”模式。所以只有当performBlock结束时才会发生重置。