mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-11 20:00:30 +01:00
Getting exceptions accessing properties of objects, due to deletions? #70
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @JoeMatt on GitHub (Aug 24, 2016).
We have a bunch of random CoreData crashes in our user crash logs that we rarely see in our tests. All due to being unable to resolve a fault. Or scheme looks basically like this.
Book.chapters -> [Chapters].pages-> [Pages]
We never delete pages directly, but a chapter will get a new array of of pages and the pages are set to delete in the .xcscheme when they lose their parent.
In another part of the code there might be something that working the old pages they just got from a fetch. I go to access a property of a page that, I'm guessing here, has been cleared by CData. Our network code is all async so we'd be doing this work in another thread.
How are we supposed to be handling this situation? I know CStore is handling threading for us for queries and inserts and such, but once I have an object another thread could at the same time delete it before I finish my work with it. I think this is what's causing our random crashes since it's only happening on object types that sometimes get deleted while the app is running.
Sorry if this is more a core data question and not specific to CoreStore, this is my first large scale CoreData app and the only Google queries related to these crashes suggest looking at threads but like I said, I'm not specifically deleting these objects, it's directly after fetching the array so it might be a very tight race condition but it's effecting about 6% of all sessions with crashes.
@JohnEstropia commented on GitHub (Aug 24, 2016):
First of all, make sure your relationships are properly set with inverse-relationships.
Other than that, I think the only way to avoid this is to look for ways to protect your "pages" from being accessed after getting deleted (via cascade deletion).
One way we work around this is to just set the Delete Action to "Nullify" and set a flag such as "isRemoved" to indicate that the objects is in a "deleted" state. Doing so, the "deletion" is transparent to CoreData and your objects will not be in an unreliable state. The app can then delete those objects in a non-critical time (e.g. during app launch)
@JoeMatt commented on GitHub (Aug 24, 2016):
This is really helpful, I'll give that a go, thanks.
@JohnEstropia commented on GitHub (Aug 24, 2016):
Just to make sure though, do you have any stack trace we can check? Or some code to give an idea of how your transactions are set up? Since CoreStore implements all updates in a serial transaction, there should not be a case where multiple contexts (threads) access deleted objects from other contexts (or at least not explicitly). It's either we're hitting a Core Data bug, or your objects are being retained somewhere.
@JoeMatt commented on GitHub (Aug 26, 2016):
I'm leaving for vacation for 2 weeks so I can't get a good code sample. I made some tweaks in a few parts and we're going to see if our crash numbers improve.
For some reason we have a lot of users crashing on DB init also. I copied the code right out of the sample so not sure what that's about either.
This is the corestore error,
What's weird is that this code hasn't changed for many releases except adding new versions to the migration chain. But in our testing of migration between versions we haven't seen crashes. I would also expect it to just dump the old DB and create a new one if that was the issue. We have been updating CoreStore versions with each release though to match the newest, so I wonder if something in CS was updated that would be crashing here?
I switched to the new v2 init methods for our next release, probably won't fix it but maybe?
@JohnEstropia commented on GitHub (Aug 26, 2016):
I think the problem is you have migrate-able models specified with
MigrationChain, but you are using the synchronousaddSQLiteStoreAndWait()method which is documented to not support migrations.For stores that expect migrations, you should use the asynchronous
addSQLiteStore(..., completion: ...)method instead.@JohnEstropia commented on GitHub (Aug 26, 2016):
If you prefer to just dump old models and recreate new ones, try not not pass a
MigrationChainto theDataStackat all.@JoeMatt commented on GitHub (Aug 26, 2016):
Oops. ha, thanks.
If we're waiting for the store to complete migrating and the completion handler for addSQLiteStore() hasn't fired yet, what happens if queries are sent to the stack? Does it queue them or will it crash or they just disappear.
I ask since we assume with the way we do init now, since static initlizizers are in a dispatch_once(), that we can safely not worry about racing so we don't currently have a linear boot up process. We just fire off jobs and whomever hits it first we don't worry.
@JohnEstropia commented on GitHub (Aug 26, 2016):
Right now CoreStore doesn't support asynchronous fetching (sounds like a good feature though), so queries will just return empty values (
nilor[]) if no stores exist. but it should not crash as long as the entity you are querying is declared in theDataStack' s model.@JohnEstropia commented on GitHub (Aug 26, 2016):
Because I like the idea of asynchronous, lazy fetches, I added a feature request here: https://github.com/JohnEstropia/CoreStore/issues/88
@JoeMatt commented on GitHub (Aug 26, 2016):
Cool, synchronizing boot up of databases is always tricky, we have a few different stores actually plus some other data processing that happens at startup. We'll realistically have to write code to coordinate the start of these stores with a loading screen but #88 would be a good fallback just in case.
@JohnEstropia commented on GitHub (Aug 26, 2016):
I also recommend using
ListMonitors where you can. They handle store changes well so your observers are notified properly when migration completes.@JohnEstropia commented on GitHub (Aug 29, 2016):
I'm closing this issue for now, but if you have other concerns feel free to continue the discussion :)