Is there a way to instantiate an NSManagedObject without inserting it?

I have a user interface to insert a transaction. as soon as the user clicks on the plus, he gets the screen, and I want to create an instance of the Core Data NSManagedObject so that the user can work on it. Then, when the user clicks the "Save" button, I call the save function.

so before the code:

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext]; //even if i dont call save: its going to show up on my table [self.managedObjectContext save:&error] 

PS I am using NSFetchedResultsController in this table, and I see that NSFetchedResultsController inserts a section and an object into the table.

My thought is that there is a way to create an instance of the NSManagedObject transaction, I could update it while keeping it until the client goes to.

+44
iphone core-data nsmanagedobject nsfetchedresultscontroller
05 Oct '10 at 23:25
source share
6 answers

There is a fundamental problem with using nil MOC: objects in different MOCs should not refer to each other - this, apparently, also applies when one side of the relationship has zero MOC. What happens if you save? (What happens when another part of your application is saved?)

If your object does not have a relationship, then there are many things you can do (for example, NSCoding).

You might be able to use -[NSManagedObject isInserted] in NSPredicate (presumably YES between insertion and successful persistence). Alternatively, you can use a transient property with the same behavior (set it to YES in awakeFromInsert and NO in willSave). Both of these problems can be problematic if another part of your application is saved.

Using a second MOC is what CoreData is supposed to use; It automatically handles conflict detection and resolution. Of course, you do not want to create a new MOC every time there is a change; it may be confusing to have one MOC for unsaved changes by a slow "user flow" if you do not mind that some parts of the user interface see unsaved changes in other parts (the communication overhead between the MOCs is negligible).

+16
Oct 6 2018-10-10T00:
source share

What it is worth, Marcus Zarra seems to be promoting the nil contextual approach, arguing that it is expensive to create a new context. See this answer to a similar question for more information.

Update

I am currently using the nil context approach and have come across something that may be of interest to others. To create a managed object without context, you use the initWithEntity:insertIntoManagedObjectContext: NSManagedObject method. According to Apple documentation for this method:

If context not nil , this method calls [context insertObject:self] (which causes awakeFromInsert called).

The value here is important. Using the nil context when creating a managed object will prevent the insertObject: call insertObject: and therefore prevent the awakeFromInsert call. Therefore, any initialization of the object or setting the default property values ​​performed in awakeFromInsert will not be performed automatically when using the nil context.

Bottom line: when using a managed entity without context, awakeFromInsert will not be called automatically, and you may need additional code to compensate.

+29
Oct 06 '10 at 0:01
source share

this is how i handled this:

When loading, where we know that we are dealing with a new transaction, I created one out of context.

 NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext]; transaction = (Transaction *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; 

then, when it came to establishing a relationship, I did this:

 if( transaction.managedObjectContext == nil){ NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:self.managedObjectContext]; Category *category = (Category *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; category.title = ((Category *)obj).title; transaction.category = category; [category release]; } else { transaction.category = (Category *)obj; } 

and at the end to save:

 if (transaction.managedObjectContext == nil) { [self.managedObjectContext insertObject:transaction.category]; [self.managedObjectContext insertObject:transaction]; } //NSLog(@"\n saving transaction\n%@", self.transaction); NSError *error; if (![self.managedObjectContext save:&error]) { // Update to handle the error appropriately. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); // Fail } 
+17
06 Oct 2018-10-06
source share

You can insert NSManagedObjectContext with -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:] by passing nil for the context of the managed object. Of course, you should assign it to the context (using -[NSManageObjectContext insertObject:] before saving. This, as far as I know, is not really the intended template in Core Data, however (but see @mzarra answer here ). There are some complicated ordering problems (i.e. make sure that the instance is assigned to the context before it expects it to be available, etc.). A more standard template is to create a new managed context object and insert a new object into this context. When the user saves, saves the context and processes NSManagedObjectDidSaveNotification NSManagedObjectDidSaveNotification to merge the changes into your “main” context. If the user cancels the transaction, you simply reset the context and continue your business.

+7
05 Oct '10 at 23:34
source share

An NSManagedObject can be created using nil as the context, but if the other NSManagedObjects it should reference will result in an error. As I do this, I pass the context to the destination screen and create an NSManagedObject on this screen. Make all changes to other NSManagedObjects. If the user removes the cancel button, I delete NSManagedObject and save the context. If the user deletes the save button, I update the data in NSManagedObject, save it in context and release it on the screen. On the initial screen, I update the table with a reboot.

Removing the NSManagedObject on the target screen gives key time to update the file. Usually you have enough time so that you do not see the changes in the table. In the iPhone Calendar application, you have a delay from the moment it is saved to the time displayed in a table. This can be considered a good thing from the point of view of the user interface that your user will focus on the line just added. Hope this helps.

+2
Jun 29 2018-12-12T00:
source share
 transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:nil]; 

if the last parameter is nil, it will return an NSManagedObject without saving to db

-3
Jun 26 '13 at 6:25
source share



All Articles