In my application I have to send values of my NSManagedObject to server & after getting a success result from server I must update a filed in my NSManagedObject.
On the server side the id field is an integer type. Is there any possible id in Core Data which i can send to sever and update the value again in my iPhone?
Is NSManagedObjectID suitable for this ?
NSManagedObjectID is really not appropriate for this. It's not numeric and doesn't convert to a numeric form. And if you're communicating on a server-- can the user use the same server account from more than one device? Because NSManagedObjectID is only valid on the device where the object was created. You can't create a managed object and tell it what object ID to use.
If you need a unique, numeric ID, you need to create one yourself. Add a numeric attribute to the entity description and use it for your own ID values. Core Data does not provide this, but it's easy to do it yourself.
NSManagedObjectID is fully under Core Data's control. That means you have little if no control over it. Say you're creating a database from fresh using data from the server, there is no way to instruct Core Data to reuse specific NSManagedObjectIDs (so you'll have to update the IDs on the server). NSManagedObjectID is meant to be used within Core Data in most cases.
You should use your own unique IDs, and this is pretty easily done with the following code:
NSString* uuid = [NSUUID new].UUIDString;
NSString* entityID = [[NSString alloc] initWithFormat: #"%#/%#", self.entity.name, uuid];
You can use either the uuid directly or use another ID scheme like /YourEntityName/<uuid> or whatever suits you.
NSManagedObjectID is unique enough for that purpose, no problem. But it changes its value exactly once - at leat it may. That is when a transient object becomes persistent. So make sure to save the context before you fetch the NSManagedObject's ID.
Related
I am new to core data and iphone programming so dont mind my silly qn.
I couldn't figure out how to mark a attribute as a primary key in the xcdatamodel file or may be outside. I looked around and found some people saying that it is not possible.
I am getting identifier for every object that i am getting, i would need to store that object through core data and i might need to use that identifier in my web service to retrieve additional data.
How do i keep the primary key of an entity equal to that identifier, any help is greatly appreciated.
Thanks in advance,
Yogesh
In short you cannot mark an attribute as primary key automatically. You have maintain one by your own.
You can do anyone of the below:
Use [NSManagedObject objectID].
Your own primary key-like system that stores an integer in your model and increments it with the creation of each object
You shouldn't be thinking about Core Data as a database structure with tables and keys. That's just an implementation detail.
To get an entity with a partucular you create a fetch request into your data store for that identifier and it will retrieve that object into a managed object context.
If you are worried about performance, you can make the attribute that stored this identifiers as indexed in the data model.
I want to have table in CoreData that holds a list of other CoreData objects I have accessed, for instance I have Clients and I want a table RecentClients that is simply holding this list and the date they were accessed.
Can I store the objectID and then do a fetch request based on that?
EDIT:
See Ben's answer below and then go here:
http://cocoawithlove.com/2008/08/safely-fetching-nsmanagedobject-by-uri.html
You'll want to convert the NSManagedObjectID to a string by calling its -URIRepresentation method. You can then convert the string back to an NSManagedObjectID using NSPersistentStore's -managedObjectIDForURIRepresentation: method.
If you store the strings, you should be able to do what you're describing, though you won't use a fetch request; you'll use -[NSManagedObjectContext objectWithID:]
How are you planning on storing the access date? If you make it an attribute of your Client entity, you can bump it each time the object is accessed and then use an NSFetchedResultsController that fetches Clients ordered by the access date. The downside is, of course, that you're modifying the instance every time you access it, which may not be ideal.
You could just create the RecentClients as another entity in your Core Data model. It would then have a one to many relationship with the Client entity.
I want to use core data in my application with back end Sqlite store.
But I need the Primary key (auto inc Integer) value after an insert which I want to send this primary key value to a web server.
Is there any way to get the primary key of the record from sqlite database through the core data feature ?
I don't want the unique ID of NsmanagementObject ObjectID
Thanks,
Sridhar
You can't get the primary key of the Core Data table - it is abstracted away on purpose.
If you need some kind of externally addressable identity attribute, you could roll your own, though it's not clear why you don't want to use the NSManagedObjectID, which is the closest thing to an 'ID' column in Core Data-land. There is a category that allows it to be easily transformed into a URI that can be stored external to the application.
If you want to roll your own, plug into the NSManagedObject lifecycle methods like willSave, etc...
use sqlite3_last_insert_rowid(sqlite3*) function
The CoreData documentation says "You can sometimes benefit from creating your own unique ID (UUID) property which can be defined and set for newly inserted objects. This allows you to efficiently locate specific objects using predicates (though before a save operation new objects can be found only in their original context)."
What should be used for this type?
A managed object's objectID is usually 'NSManagedObjectID' type but the DataModel wizard tool via XCode that allows you to set the type for a given attribute only has the basic allowed types in addition to 'Undefined', Binary Data, & Transformable.
If I wanted to have an attribute that serves as a secondary id for an object (in addition to it's standard ObjectID), do you store it as an NSString or would you custom modify the object model to hold NSManagedObjectID?
(for iPhone app/CoreData development)
An NSString or integer attribute are logical choices, though you could use a transformable attribute to store anything you wanted (that could be appropriately serialized, of course). An incrementing integer is probably good enough for many uses, but each use case is different. Many algorithms exist on the net for generating string or byte-array UUIDs (start with Google). An NSString UUID is quite easy:
+(NSString*)UUIDString {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return [NSMakeCollectable(string) autorelease];
}
for an array of bytes, look at CFUUIDGetUUIDBytes().
Before you go this route, think long and hard about whether it is necessary. Folks coming from a SQL point of view "want" their ids, but Core Data is not about relational databases. It's an object graph management framework that just happens to use SQLite as one backing implementation. If you're trying to do SQL-like things in Core Data, you're going to be fighting the framework. There's often a way around needing a separate id property in proper usage of the Core Data framework.
I need some advice how to go about this:
1) I retrieve an XML from a web server.
2) I want to store all the entities (i.e. Friends) from that XML locally on the device, using Core Data.
3) So I parse the XML and make an Managed Object for every Friend in that XML
4) But I want to make sure that I don't add one Friend multiple times into the DB. How could I achieve that?
-------------- my strategy thoughts on this ----------------
A) While parsing the XML, I create an Managed Object of the Friend entity as soon as there is a Friend element started. At that point I don't know which friend it will be, until the NSXMLParser stepped through all the upcoming attributes like firstName, id, etc.; After the End-tag for the Friend element, I have that friend in my Managed Object Context. Then I make an NSFetchRequest to see if that friend is stored already. Problem is, that the new friend is already part of the context, so probably Core Data will return always a match!?
B) I need two different Managed Object Contexts so that the parsed Friends first go into MOC_A, and then I query MOC_B (the actual local store) without that the new parsed friends disturbe my query to the local store. So I can find out if the friend already existed.
C) While parsing a friend from the XML I just create a new Managed Object instance WITHOUT adding it to an Managed Object Context (possible ?!). Later, when the friend is pares completely, I check against Core Data if it is stored. If not, I add it. Otherwise I throw the object away.
D) I need another strategy.
You should use a new indexed attribute in your Core Data entity to store the unique ID from the XML. Before adding an object, you will have to manually check if an object with that ID already exists.
UPDATE
The key is to not add a managed object to the context until you have determined that it is new.
This is pretty straightforward given the unique ID, but it sounds like you can't parse for the unique ID first. In that case you should use a temporary mutable dictionary (NSMutableDictionary) to store the data as it's parsed.
If you determine that the friend is new, you can create it and copy the data over from the dictionary. If the friend is not new, you can discard the dictionary.