Updating an Item in Core Data - iphone

I am new to Core Data. I fetch few objects into an NSMutableArray.
Now I want to update an object with objectID x.
My question is:
How do I get the objectId for an object?
and then how do I perform updates on that particular object? (eg: change 'Name' attribute and save)
Thanks

You get the ID by calling [myObject objectID]. You can update and save a new value by calling your objects accessors like you would with any other object. Then to write the changes to the persistent store you do:
NSError *error;
if (![managedObjectContext save:&error]) {
// Handle the error.
}

Related

iPhone - Core Data : forgetting object

I am inserting new entries to a core data entity using this
newEntry = [NSEntityDescription insertNewObjectForEntityForName:#"myEntity" inManagedObjectContext:context];
after that, I populate newEntry properties but at some point, and before this newEntry is saved to the context, I may want to remove this newEntry from the "buffer" or whatever, so it will not be saved when I commit the changes.
How do I do that? I have tried to use reset and rollback but it had no effect and the object continues to be saved.
thanks
[context deleteObject:newEntry];
This will remove it from the context.
More information and sample code

Saving two many-to-many entities in Core Data that require each other

I have two core data entities in my iOS app, Catalog and Product. They both possess a many-to-many relationship with require to the other entity. The data that I'm using to populate these entities are from an XML file. Currently, in parser: didEndElement: I save a Catalog entity, like so:
if ([elementName isEqualToString:#"catalog"])
{
// Sanity check
if(currentEatery != nil)
{
NSError *error;
// Store what we imported already
if (![managedObjectContext save:&error]) {
// Handle the error.
NSLog(#"Eatery error: %#", [error domain]);
}
}
}
However, I do not know how to save Catalog without first saving a Product to populate it with. Does anyone have any suggestions? I can post more code to clarify this if necessary.
You can parse your entire xml file and save the context when you are done (I've done it with no problems). Once you have finished parsing and creating all entities you will have all the products and catalogs linked. This will also make your file parsing faster.

Core Data primary key ID for a row in the database

Suppose I have a list of books stored in Core Data. I want to search for a book by it's primary key ID.
I know the sqlite file created by Core Data has an ID column in each table, but this doesn't seem to be exposed to me in anyway.
Does anyone have any recommendations?
-[NSManagedObject objectID] is the unique ID for an object instance in Core Data. It can be serialized via -[NSManagedObjectID URIRepresentation]. You can retrieve the objectID from a persistent store coordinator with -[NSPersistentStoreCoordinator managedObjectIDForURIRepresentation:] and then get the object from a managed object context with -[NSManagedObjectContext objectWithID:].
BUT
You should keep in mind that Core Data is not an ORM. It is an object graph management framework. That is uses SQLite (and unique row IDs) as a backend is purely an implementation detail. The sooner you can get yourself out of the SQL/RDBMS mindset, the faster you will be happy with Core Data. Instead of trying to find an object from a stored ID, consider why you need that object and what object needs it. If an instance of class Foo needs to be able to get to an instance of class Bar, why not just create an association from the Foo to the Bar and set the appropriate Bar instance as the target of the association on the appropriate Foo instance. Let Core Data keep track of object IDs.
As Barry Wark said, remember always that Core Data is not an orm. Pure SQL details are not exposed to the user and every row is just an object. By the way, sometime you should need to access the "primary key", for example when you need to sync the coredata db with external sql databases (in my case I needed it in a callback function to change the state of an object after INSERT it with success in the remote db). In this case, you can use:
objectId = [[[myCoredataObject objectID] URIRepresentation] absoluteString]
that will return a string like: x-coredata://76BA122F-0BF5-4D9D-AE3F-BD321271B004/Object/p521 that is the unique id used by Core Data to identify that object.
If you want to get back an object with that unique id:
NSManagedObject *managedObject = [managedObjectContext objectWithID:[persistentStoreCoordinator managedObjectIDForURIRepresentation:[NSURL URLWithString:objectId]]];
NB: Remember that if the receiver has not yet been saved in the CoreData Context, the object ID is a temporary value that will change when the object is saved.
This is the way you can get the object id as String using Swift from a NSManagedObject:
entity.objectID.uriRepresentation().absoluteString
in Swift this will be done by getting ID of the row as URI then get last path of URI
entity.objectID.uriRepresentation().lastPathComponent
the output of last path will look like this
p12
this output is string so you can remove the p using:
trimmingCharacters()
// Like this
let id = entity.objectID.uriRepresentation().lastPathComponent.trimmingCharacters(in: ["p"])

iphone core data loop array and save each

I have a core data model with two tables (meal and ingredients). I am trying to save ONE meal with MANY ingredients. I have the code below which loops through an array of ingredients. I'm trying to save it, but I cannot redeclare the "entity" below. How do I do it? I've tried releasing it, but that didn't work! Thanks for any help.
for (x=0;x<ingredients;x++) {
NSEntityDescription *entity = [NSEntityDescription insertNewObjectForEntityForName:#"Ingredient" inManagedObjectContext:managedObjectContext];
entity.name = #"test";
}
(this method does work saving ONE record out of the loop.. so that's not the problem)
You don't insert entities into contexts. You insert managed objects into contexts.
You should have something like:
NSManagedObject *myMO;
for (x=0;x<ingredients;x++) {
myMo = [NSEntityDescription insertNewObjectForEntityForName:#"Ingredient" inManagedObjectContext:managedObjectContext];
[myMO setValue:#"test" forKey:#"name"];
}
Of course, if have an NSManagedObject subclass you can just set the 'name' property directly.
The important thing is not confuse entities with instances of NSManagedObject or its subclasses. Entities are just descriptions of how objects relate to each other inside the object graph of the managed object context. The context uses the entity descriptions to figure out how all the actual instances fit relate to one another and how they are fetched and stored.

Can I tell Core Data to use a specific unique ID for an y object when saving it?

Example: I read data from an XML file. This data has unique id elements. I want to store those objects with their original unique id. How would I do that?
I figured out I could ask the managed object for it's ID, like this:
NSManagedObjectID *moID = [managedObject objectID];
but here the problem is: The XML tells me with the id element which object this is, and I need to look up in the database of core data if this object already exists in there, or not. So is it the only option to make an id attribute in my managed object model for that entity and then query for that? Then I will have two id systems right?
Don't worry about the ObjectID of Core Data. This is an internal unique ID which is not guarantied to be constant during the object's life cycle (e.g. it will change when you save the object to sql store). Just create a new mandatory attribute in your model and flag it as indexed so retrieval will be fast.
In the entity associated to this kind of objects, simply add another attribute of type string, call it objectID or similar and declare it to be mandatory.