iOS developers seem to be split about Core Data framework. I have seen people who feel like Core Data “just makes sense” for them to those who consider Core Data is very hard to comprehend. I definitely belonged to those in the latter.
Due to a crash in Core Data code at work, I had to take a closer look at Core Data framework ( Original author the core data code left team and I am the one who drew the short straw for ownership). This code has been working , sans crashes, for a few releases now, but since iOS 9.3 it has started randomly crashing in production ( with of course no reliable repro steps). The exact code that has crashed has not been touched for a few releases.
Due to apparent lack of explanation, I dove deep into how to debug Core data code and found this debugging nugget.
Core data debugging nugget
- Create a new Xcode scheme by selecting the tab in top left corner right before the simulator/device type and selecting “New Scheme”. Name it something eay to understand like “TestCoreData” (Using Ray Wenderlich video tutorial project as example here)
- This new scheme will not be the default selected scheme. Click on the “Scheme” tab again and this time select “Edit scheme” as shown below
- Select the “Run” option from the left menu and select the “Arguments” tab from the right side wizard. Here click on the “+” sign under the “Arguments passed on launch” tab. Here enter the text “-com.apple.CoreData.ConcurrencyDebug 1” and hit “Close” at the right bottom corner of the wizard.
The next time you launch you app with this scheme selected and if you are using your CoreData layer incorrectly, you will get a crash that is similar to the below with the entry at end of your stack trace pointing to “NSManagedObjectContext_Multithreading_Violation_AllThatIsLeftToUsIsHonor__ ” providing you the indication that you are creating your NSManagedObjectContext object (or) NSManagedObject object in one thread and using it in an another ( which is CoreData violation).
An interesting side note is that, as per Marcus Zarra, this was enabled by default in iOS 6 but then was removed because this would too many production apps to crash.
I personally think that this is a very vital part of Core Data development as it would avoid random crashes due to CoreData threading violations that are virtually impossible to root cause.
I have redesigned our app’s Core data infrastructure to take advantage of specifying parent-child relationship among NSManagedObjectContext objects while also fixing the CoreData violations across our app. I have also created a new scheme that will be shared across the team for Core Data debugging and which will also be enabled by default in Jenkins when buiding “dogfood” version of our app.
Resources where I discovered this nugget