问题
I have an application that pulls JSON data from a server, parses the data into NSManagedObject subclasses and these NSManagedObject subclasses are then used as properties in various view controllers.
The trouble I'm having is that at some point in the future the data on the server will change and this will trigger an update pull request. When attempting to update the NSManagedObject subclasses, the app is crashing if the user then attempts to modify NSManagedObject via the UI by e.g. answering a question which updates a relationship on that NSManagedObject.
Is it possible to use NSManagedObject to both display data to the user and at the same time update that NSManagedObject's record on a different thread?
This is the backtrace that I'm getting after the error:
* thread #1: tid = 0x1c03, 0x003d5e6d libsqlite3.dylib`sqlite3VdbeExec + 54749, stop reason = EXC_BAD_ACCESS (code=2, address=0x0)
frame #0: 0x003d5e6d libsqlite3.dylib`sqlite3VdbeExec + 54749
frame #1: 0x00343be1 libsqlite3.dylib`sqlite3_step + 3169
frame #2: 0x0071419f CoreData`_execute + 143
frame #3: 0x00714011 CoreData`-[NSSQLiteConnection execute] + 2801
frame #4: 0x007285ce CoreData`-[NSSQLChannel selectRowsWithStatement:] + 94
frame #5: 0x0073128f CoreData`newFetchedRowsForFetchPlan_MT + 1279
frame #6: 0x0071c6e3 CoreData`-[NSSQLCore newRowsForFetchPlan:] + 323
frame #7: 0x0071be07 CoreData`-[NSSQLCore objectsForFetchRequest:inContext:] + 711
frame #8: 0x0071b8f4 CoreData`-[NSSQLCore executeRequest:withContext:error:] + 404
frame #9: 0x0071aa6d CoreData`-[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 2445
frame #10: 0x007189c9 CoreData`-[NSManagedObjectContext executeFetchRequest:error:] + 569
frame #11: 0x0002f7a4 TQ`+[QTQCoreDataManager retrieveAllEntriesForEntityName:stringPredicate:orderBy:ascendingOrder:managedObjectContext:] + 532 at QTQCoreDataManager.m:103
frame #12: 0x0002fbcb TQ`+[QTQCoreDataManager retrieveFirstEntryForEntityName:stringPredicate:orderBy:ascendingOrder:managedObjectContext:] + 203 at QTQCoreDataManager.m:149
frame #13: 0x0002faa2 TQ`+[QTQCoreDataManager retrieveFirstEntryForEntityName:stringPredicate:orderBy:ascendingOrder:] + 226 at QTQCoreDataManager.m:129
frame #14: 0x000dd65e TQ`-[QTQTopic latestAnsweredSession] + 238 at QTQTopic.m:228
frame #15: 0x000dca29 TQ`-[QTQTopic isCompleted] + 185 at QTQTopic.m:157
frame #16: 0x000b5362 TQ`-[QTQTopicContainerViewController closeButtonPressed:] + 1442 at QTQTopicContainerViewController.m:376
frame #17: 0x01be2705 libobjc.A.dylib`-[NSObject performSelector:withObject:withObject:] + 77
frame #18: 0x00b19920 UIKit`-[UIApplication sendAction:to:from:forEvent:] + 96
frame #19: 0x00b198b8 UIKit`-[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
frame #20: 0x00bda671 UIKit`-[UIControl sendAction:to:forEvent:] + 66
frame #21: 0x00bdabcf UIKit`-[UIControl(Internal) _sendActionsForEvents:withEvent:] + 578
frame #22: 0x00bd9d38 UIKit`-[UIControl touchesEnded:withEvent:] + 546
frame #23: 0x00b4933f UIKit`-[UIWindow _sendTouchesForEvent:] + 846
frame #24: 0x00b49552 UIKit`-[UIWindow sendEvent:] + 273
frame #25: 0x00b273aa UIKit`-[UIApplication sendEvent:] + 436
frame #26: 0x00b18cf8 UIKit`_UIApplicationHandleEvent + 9874
frame #27: 0x02e47df9 GraphicsServices`_PurpleEventCallback + 339
frame #28: 0x02e47ad0 GraphicsServices`PurpleEventCallback + 46
frame #29: 0x02166bf5 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
frame #30: 0x02166962 CoreFoundation`__CFRunLoopDoSource1 + 146
frame #31: 0x02197bb6 CoreFoundation`__CFRunLoopRun + 2118
frame #32: 0x02196f44 CoreFoundation`CFRunLoopRunSpecific + 276
frame #33: 0x02196e1b CoreFoundation`CFRunLoopRunInMode + 123
frame #34: 0x02e467e3 GraphicsServices`GSEventRunModal + 88
frame #35: 0x02e46668 GraphicsServices`GSEventRun + 104
frame #36: 0x00b1665c UIKit`UIApplicationMain + 1211
frame #37: 0x00005fcd TQ`main + 141 at main.m:16
回答1:
kinda.. not the same MO but the same entity.
the thing is that MOs aren't threadsafe but objectIDs are
so...
get the MO in main thread for UI
get its ObjectID and use it in bg thread (fetch it again here)
update the object after you are done in main thread (call
[context refreshObject:object
])
来源:https://stackoverflow.com/questions/14401006/exc-bad-access-crash-when-updating-nsmanagedobject