Create an NSManagedObject Without Saving? [duplicate]
Asked Answered
M

4

9

Possible Duplicate:
Store But Don't Save NSManagedObject to CoreData?

I need to make an NSManagedObject without saving it, how can I do this?

The reason I want to do this is the app has a setup in which the user enters their details, however I only want to save the object if they complete the setup (they have the option to cancel, in which case the object needs to be discarded without being saved, which is why I don't want to insert it straight away).

I have tried insetting one without a context but the app crashes.

I have tried the following:

GuestInfo *guest;
guest = (GuestInfo *)[NSEntityDescription insertNewObjectForEntityForName:@"GuestInfo" inManagedObjectContext:nil];

This causes the crash with the following error message:

'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'GuestInfo''
Mesothelium answered 15/4, 2012 at 22:10 Comment(4)
why don't you show us your code?Bi
What are you actually using this object for if you do not need to persist it? Can you not just create another object with the same interface?Christogram
If you want to insert an NSManagedObject then you need to have a context to put it in. However, I agree with @ChristogramTirade
The reason I want to do this is the app has a setup in which the user enters their details, however I only want to save the object if they complete the setup (they have the option to cancel, in which case the object needs to be discarded without being saved, which is why I don't want to insert it straight away).Mesothelium
S
14

I would recommend creating the managed object and inserting into your managed object context as normal. You will have a reference to the managed object, i.e.:

GuestInfo* guest = (GuestInfo *)[NSEntityDescription insertNewObjectForEntityForName:@"GuestInfo" inManagedObjectContext:managedObjectContext];

Then if the user cancels, just delete it from the managed object context like this:

[guest deleteInContext:managedObjectContext];

The managed object context is designed as a scratchpad for you to create and delete objects in it like this.

Another option you might consider is calling:

[managedObjectContext rollback]

if the user cancels. i.e. you would create the managed object in the managed object context, but if the user cancels, you undo or rollback the state of the managed object context to how it was at the last time it was saved. See the "Undo Management" section of the Apple's "Using Managed Objects" doc:

https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CoreData/Articles/cdUsingMOs.html

Skilken answered 16/4, 2012 at 11:49 Comment(0)
C
7

Create a NSManagedObjectContext, as a child of your normal context. You can make all the changes in there that you want, and as long as you don't call save, the stuff in there will not get pushed.

For example...

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType];
moc.parentContext = myCurrentManagedObjectContext;

Now, from within any thread in your program, you can make the following call...

[moc performBlock:^{
    // Do anything you want to with this context... make a new object, whatever.
    // As long as you do not call [moc save], your changes will not propagate
    // up to the parent context, nor saved.
}];
Checkerbloom answered 15/4, 2012 at 22:34 Comment(3)
Forgive me Im new to CoreData, I have tried the first bit and I crash with: 'Parent NSManagedObjectContext must use either NSPrivateQueueConcurrencyType or NSMainQueueConcurrencyType.'. Then, trying that method I get an error saying there is no visible interface fir the context which declares performWork.Mesothelium
You need to provide more information then. Specifically, how are you creating your "current" MOC? If you are doing it with just alloc/init, try creating it with alloc/initWithCurrencyType: NSMainQueueConcurrencyType which will be just fine, if your app is only using the main thread anyway. Regarding performWork.. type. I fixed it in the answer.Checkerbloom
This. Using a private context to create possibly transient managed objects is a much better solution than inserting the object into the main context and then deleting it if it's not needed (as the currently accepted answer suggests). In addition to a clean design you get a lot of other benefits from this approach as well.Ornas
T
0

Managed objects always need to have a context. If you don't want the objects to be persistent, simply don't save the context.

If you never want your objects to be persistent, it is questionable if you should actually use Core Data.

Traherne answered 16/4, 2012 at 1:6 Comment(4)
If I must always use a context, then why would it be that when calling insertNewObjectForEntityForName:inManagedObjectContext: does it instantly add the object to CoreData just with null values? I want to create the object but not save it unless the user confirms to at a later stage.Mesothelium
So? Inserting an object in a managed object context does not save it. You would have to do that explicitly by calling save:.Traherne
I think this is wrong? When I use insertNewObjectForEntityForName:inManagedObjectContext and then (before calling save!) perform a fetch on coredata the object shows up.Lanti
@KevinGrabher A fetch request can return objects that haven't been saved yet. To quote from the NSManagedObjectContext docs: "An object that meets the criteria specified by request (...) and that has been inserted into a context but which is not yet saved to a persistent store, is retrieved if the fetch request is executed on that context."Traherne
B
-1

It is a bit strange to make a Core Data object if you don't want to save it....but anyway the error says that you have no model file named GuestInfo included in your project. Verify that it exists and is included in your Copy Bundle Resources section. The model file is the one where you declare the types in your database and the connections between them.

Bliss answered 15/4, 2012 at 23:25 Comment(2)
The reason for that error is actually that the insertNewObjectForEntityForName:inManagedObjectContext: method infers the model from its context parameter (which is nil here). That doesn't necessarily mean that the model file isn't present.Traherne
@Traherne I mean it isn't present in the form that is being looked for...but I admit I did overlook that the context was nil ^^;Bliss

© 2022 - 2024 — McMap. All rights reserved.