Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Support creating a temporary object (MOC = nil) with +createInContext: #546

Closed
airdrummingfool opened this Issue · 11 comments

5 participants

Tommy Goode Tony Arnold Luke Dixon John Tumminaro James Richard
Tommy Goode

Using +createInContext: and passing nil results in an assertion error. Creating the entity using the standard initWithEntity:insertIntoManagedObjectContext: and passing nil for the context works, and returns an instance of the entity that is not persisted on any context. This is useful for creating temporary objects that do not get saved or show up in fetches.

+createInContext calls +insertInManagedObjectContext: (which is on the entity generated with Mogenerator), which performs an assert on the MOC and then calls [NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:].

Tony Arnold
Owner

This is included in MagicalRecord 2.3.0 and higher.

Tony Arnold tonyarnold closed this
Luke Dixon

Hi Tony,

I'm using the head version of MR and I'm attempting to use the MR_createEntityInContext: method to create disconnected temporary objects, like so:

ManagedObject *managedObject = [ManagedObject MR_createEntityInContext:nil];
manageObject.title = @"Title";

And saving like so:

[[NSManagedObjectContext MR_defaultContext] insertObject:managedObject];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

However, when I check the sql database the title hasn't been saved. Am I doing something wrong? Any help would be greatly appreciated.

Thanks

John Tumminaro

Don't use MR_createEntityInContext:nil, use MR_createEntity instead. Here is the full process:

ManagedObject *managedObject = [ManagedObject MR_createEntity];
manageObject.title = @"Title";
[[NSManagedObjectContext MR_defaultContext] MR_saveOnlySelfAndWait];

You don't need to do MR_saveToPersistentStoreAndWait unless you really need the data saved synchronously to the persistent store which defeats the purpose of the two context stack that MagicalRecord uses.

Luke Dixon

Thanks for the prompt response. However, won't using MR_createEntity connect that object to the default context and therefore be persistent and not temporary? What happens if I decide not to save the object to the context?

James Richard
Luke Dixon

I've tried doing this:

NSManagedObject *managedObject = [NSManagedObject MR_createEntityInContext:[NSManagedObjectContext MR_newContext]];
    [managedObject setTitle:@"Foo"];

    if ([managedObject managedObjectContext]) {
        [[managedObject managedObjectContext] MR_saveOnlySelfAndWait];
    }

    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

However the NSManagedObject isn't saved to the persistent store, any ideas? I'm using v2.3.0-beta.2 btw, could this be causing issues?

James Richard
Tony Arnold
Owner

@lukedixon your original approach looks sound to me, with one change:

ManagedObject *managedObject = [ManagedObject MR_createEntityInContext:nil];
manageObject.title = @"Title";

// And saving like so:

[[NSManagedObjectContext MR_rootSavingContext] insertObject:managedObject];
[[NSManagedObjectContext MR_rootSavingContext] MR_saveOnlySelfAndWait];

So one of the changes I'm working on for MagicalRecord 2.3 and higher is that I'd like to start treating MR_defaultContext as read only — it's good for observing and binding to your UI, but it's best not to use it to write changes — what you're seeing is a bug, but it's not necessarily incorrect behaviour down the line. Try performing the same tasks on MR_rootSavingContext and everything should work.

A simpler, cleaner approach might be:

ManagedObject *managedObject = [ManagedObject MR_createEntityInContext:nil];
manageObject.title = @"Title";

// Now save:

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    [localContext insertObject:managedObject];
}];
Tony Arnold tonyarnold added this to the 2.3.0 milestone
Tony Arnold tonyarnold self-assigned this
Luke Dixon

@tonyarnold thanks, however I'm still having the problem of the missing title in the persistent store.

This doesn't work (in persistent store; title == NULL):

ManagedObject *managedObject = [ManagedObject MR_createEntityInContext:nil];
manageObject.title = @"Title";

// Now save:
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    [localContext insertObject:managedObject];
}];

However this does (in persistent store; title == "Title"):

ManagedObject *managedObject = [ManagedObject MR_createEntityInContext:nil];
manageObject.title = @"Title";

// Now save:
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    [localContext insertObject:managedObject];
    manageObject.title = @"Title";
}];

Any thoughts? Could this be a beta bug?

EDIT:

So, I tried the first example and it works (thanks a million). So the working code is:

ManagedObject *managedObject = [ManagedObject MR_createEntityInContext:nil];
manageObject.title = @"Title";

// And saving like so:

[[NSManagedObjectContext MR_rootSavingContext] insertObject:managedObject];
[[NSManagedObjectContext MR_rootSavingContext] MR_saveOnlySelfAndWait];

As you say though, the second example is cleaner therefore it would be interesting to know why that isn't working as expected.

Thanks again!

Tony Arnold
Owner

It's entirely possible that it is — I'm going to need to work up a test to check.

Luke Dixon

Thanks @tonyarnold - if I find anything else that will help I'll post it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.