I am writing a Core Data app and I’ve started passing my objects around to my views & managers. For example, my UIImageView subclass knows how to pull the image data out of the object, and if the image data hasn’t been loaded it knows how to fetch, assign, and use the image. I have a singleton manager to upload data to the server and those take managed objects and then update them with the server IDs on successful uploads.
This seems to be the wrong approach now that I am deleting managed objects (server tells me the objects have been deleted on the server side). The problem is that objects can get deleted out from underneath my views & managers.
Some more examples: If a completion block is still holding the object, it will be called with a deleted managed object. If a notification or user event makes it to a view before it disappears, it will attempt to access a deleted object as well. Yes, my table views / collection views will refresh and remove the associated views when underlying objects are deleted (and no longer match my fetch predicates), but there are still completion blocks.
Is it safe to be passing managed objects around like this if objects are going to be deleted? This approach so far has worked like a dream, I’m starting to think I need to completely decouple managed objects from all of my views and managers. That is, the controller fetches objects, creates the views/cells and sets all of the needed data (including IDs to reference the objects when delegate actions happen), and then lets the objects fault out again. When a user interacts with the view in any way, it must call back to the controller, fetch the associated object, and use that data. Should I stop holding on to my managed objects, or is there a clean way to just check .isDeleted all over the place?
If your moc is only doing work on the main thread, then its probably not too dangerous but not what I would say is a good design decision. If you are doing your moc work off the main thread (private dispatch queue or using the new-ado-of-ios5 option to have the moc use a private queue), then what you are doing is foolhardy.
I have a similar design but use the new-private-queue option on the moc. Any object that wants something from the moc must get it via my singleton’s interface, which does uses a ‘performBlock’ command. The nice thing about this design is that when I write, I just use ‘performBlock’. Retrieving information is obviously done using ‘performBlockAndWait’.
This interface gives me a lot of freedome to refactor the Core Data code and not have to touch anything else (which I’ve done 4 times now).
EDIT: There is more specifics in this link