Thanks very much for reading.
Our app uses multiple NSManagedObjectContexts on multiple threads. We do the following...
- We want to run a background task that downloads data.
- We spin up a background thread.
- That thread creates a child context from the main one.
- Download some JSON
- Use that new data to update managed objects, creating them when necessary, object identity is tracked via a "uuid" string property.
- Save that background thread's context.
- Background thread goes away, taking the child context with it.
On the foreground thread we are seeing a rare probably-a-timing-bug where some of our objects clone themselves in the UI. We see two copies of things in very strange ways. Different sets of objects double at different times, and they have a tendency to go away again if you wait a bit. Below is an LLDB session that demonstrates that I have an NSManagedObject that has a relationship with duplicates in it. Those duplicates have the same objectID.
I've found this to be reasonably reproducible in our app by picking an object and having it sync with the network version every few seconds.
My question is: what can I do about this? How can I prevent it? I'd love to file a radar but I can be a bit more helpful if I can understand this problem a little better and exactly what I'm doing that is causing it.
Thanks again.
// Here is an object, it is a NSManagedObject subclass
(lldb) po [order class]
Order
(lldb) po [order superclass]
OfficeV3Syncable
(lldb) po [[order superclass] superclass]
NSManagedObject
// here is one of it's relationships to another managed object: "OrderLine"
(lldb) expression (NSArray*)[[order orderLines] allObjects]
(NSArray *) $15 = 0x15b703e0
(lldb) po [$15 count]
8
// here is one of those objects, let's look at it
(lldb) expression $15[1]
(OrderLine_OrderLine_ *) $17 = 0x158f12e0
(lldb) po [$17 objectID]
0x158ed960 <x-coredata://E17717A3-D026-4EC1-AE65-F33741008328/OrderLine/p37>
(lldb) p (BOOL)[[$17 objectID] isTemporaryID]
(BOOL) $21 = NO
// here's another one, a few interesting things:
// 1. The two objects are at different memory addresses
// 2. The managedObjectIDs match
// 3. Even the memory address of the managedObjectIDs matches
(lldb) expression $15[7]
(OrderLine_OrderLine_ *) $19 = 0x15c22c90
(lldb) po [$19 objectID]
0x158ed960 <x-coredata://E17717A3-D026-4EC1-AE65-F33741008328/OrderLine/p37>
(lldb) p (BOOL)[[$19 objectID] isTemporaryID]
(BOOL) $22 = NO