Search code examples
iosobjective-cswiftuitableviewnsmanagedobjectcontext

iOS: Random error message from iOS14 EXC_BAD_ACCESS thread Queue: NSManagedObjectContext NSInternalAdditions forgetObject propagateToObjectStore


Since the new installation iOS 14.0, I have a curious bug that is firing either when I click on a tableview, either when I click on a button, either I open a popover. It is very random, and very hard to reproduce perfectly. The console of xcode is not very talkative about the problem. I have this error message in the thread:

//BUG EXAMPLE 1

#4 0x0000000189c378e8 in -[NSManagedObjectContext(_NSInternalAdditions) _forgetObject:propagateToObjectStore:removeFromRegistry:] ()

And this in the main view:

Thread 12: EXC_BAD_ACCESS (code=1, address=0x4)

Window1 Window2

//BUG EXAMPLE 2

Window1 Window2

//BUG EXAMPLE 3
Window1Window2

It says that the Thread of the NSManagedObjectContext caused the crash.
enter image description here I have problems to get more informations about the bug...

Any ideas?


Solution

  • The error suggested that there was a CoreData action done on a different thread that the one it should.

    According to the doc, you can use perform() (async) or performAndWait() (sync) to ensure that you are doing the calls in the correct queue.

    You use contexts using the queue-based concurrency types in conjunction with perform(:) and performAndWait(:). You group “standard” messages to send to the context within a block to pass to one of these methods. There are two exceptions:

    Setter methods on queue-based managed object contexts are thread-safe. You can invoke these methods directly on any thread.

    If your code is executing on the main thread, you can invoke methods on the main queue style contexts directly instead of using the block based API.

    perform(:) and performAndWait(:) ensure the block operations are executed on the queue specified for the context. The perform(:) method returns immediately and the context executes the block methods on its own thread. With the performAndWait(:) method, the context still executes the block methods on its own thread, but the method doesn’t return until the block is executed.

    When you init your context, it will be attached to some queue, and you won't know which one, but by calling that method (either perform or performAndWait) you'll be sure to do it in the correct one.