views:

42

answers:

2

Basic app layout using the navigation controller template with core date:

Delegate: persistenceCoordinator, managedObjectModel, managedObjectContext

  • RootView: managedObjectContext (from delegate), addManagedObjectContext (using the pattern from the templates), fetchResultsController
    • Add/Edit view (a hierarchy for adding Object A & its B)

I have two objects, A & B that share a 1-to-1 relationship/inverse relationship

Using the pattern from the templates the app:

  1. Creates an addManagedObjectContext
  2. Inserts an A entity
  3. Pushes on the Add/Edit A view (having passed it the inserted entity)

EXCEPTION STEPS 1:

If I simply fill in the A attributes and save everything works fine.

  • The object is inserted into the database (verified with sqlite3 on the command line)
  • The fetchResultsController updates the list view
  • I can close and open the app (full close/open not just app switch) and the list view will re fetch correctly

If I then Edit A, I can select Add B and an add B view is pushed on (and passed the A entity)

  • Fill in B details and save
  • B is inserted into A's managedObjectContext, the relationship is set, and the context is saved
  • The view pops off and all appears well
  • The objects are both in the database with the correct relationship
  • I can reload the record and see the relationship, make edits etc
  • EXCEPTION: If I close/reopen the app, so as to trigger a fetch, then the error mentioned in the title will occur.

EXCEPTION STEPS 2:

If I fill in the A attributes AND the B attributes in the initial "add"

  • Saving B triggers a full save of A's context (as above)
  • Saving A saves via the delegate relationship set up by the template (and merges the result into the main managedObjectContext etc)
  • The objects are inserted into the database correctly
  • However the fetchResultsController DOES NOT update to show the new records
  • EXCEPTION: If I close/reopen the app, so as to trigger a fetch, then the error mentioned in the title will occur.

I've tried saving A first, adding a separate context for B etc etc. I'm confused to say the least. Any help would be greatly appreciated.

Cheers, Ryan

+2  A: 

It sounds like you have two or more managed object context when you just need one.

I don't know why you would have a method called addManagedObjectContext in the RootViewController or what it would do. In all but the most complex designs, you have only one context at a time and they don't overlap. The context/s should be held by the app delegate or a dedicated model object. You would never create a new context every time you open a particular view.

You can have different context all writing to the same persistent store so I think this is why you are seeing the data in the store. However, you can't maintain graph integrity across context if you put one object in a relationship in one context and the other side of the relationship in another context. I believe this is what is producing your error.

TechZen
Having an adding context keeps all changes out of the main context until you merge them. It's perfectly reasonable.The problem was a threading issue with one of my managed objects. A silly mistake unrelated to the contexts or flow of the app.Thanks anyway. I appreciate the thoughts.
Ryan Booker
Sorry, going by the method name, I thought that you were "adding another context" and not having "a context for adding objects". For the benefit of future readers, you might want to edit your question to reflect that.
TechZen
Having more than one context just to throw objects away is an **edge** case at best. It is not "perfectly reasonable" but an unfortunately bad example that exists in one of the Apple sample source projects. `NSUndoManager` is what should be used for throw away situations.
Marcus S. Zarra
@Marcus S. Zarra -- Yes, I've never understood the multiplicity of context used by Apple and others in non-threaded cases. Like your book by the way.
TechZen
I've come to agree with Marcus (after twitter discussion and reading his book) and by extension TechZen. I was using this pattern based on the mentioned sample code from Apple. However, if you actually NEED a separate context (I don't and you probably don't either), there is still a lesson in here with regard to threading. :)
Ryan Booker
A: 

This error is generally related to threading and probably means something is still processing on another thread. In my case I was doing something stupid in a managed object's init (don't override init ;)).

Ryan Booker