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

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.

Related

In Objectify, how do you load an entity by ID without knowing the parent key?

I have an entity group in objectify, typical SomeParentClass and SomeChildClass. I want to do something like this to load an instance of SomeChildClass from the datastore.
ofy().load.type(SomeChildClass.class).id(idOfSomeChildClassInstace);
This is returning nothing found. Seems that you need to know the parent of SomeChildClass to get it from the datestore. This I know works.
Key<SomeChildClass> k = Key.create(someParentClass.generateKey(), SomeChildClass.class, idOfSomeChildClassInstace);
ofy().load().key(k).now;
What if I want to load an instance of SomeChildClass without knowing the parent, by just having the id of SomeChildClass.
You cannot do that - the actual full identifier of an entity is the kind and id of each of its ancestors as well as it's own kind and id. That is why building the full key works, but using just the child entity id does not. Another way of looking at it that ids are only unique between siblings of the same parent.
The easiest way to solve your issue is to produce a key for your child entity, then get the 'web safe string' for it. This string contains all the information of the entity and all it's parents and can be used to fully reconstitute the full id.
Using objectify:
String websafeKey = Key.create(parentKey, Entity.class, id).getString();
Key<Entity> key = Key.create(websafeKey);
You can also do this with the low level api if you need to.
You need to know the whole Key to be able to get() an entity. A child key consists of: kind, ID and parent key. So you need to provide all three.

core data, how get entity id

i tried get entity ID like that:
NSLog(#"entity id: %#",[channel objectID]);
but in this case id is not number
output:
2011-09-11 20:40:39.932 n[3591:207] entity id: 0x591f6f0 <x-coredata://4FE0AAD6-289E-404D-B81A-0FC0917BE025/Channel/p3>
why it not returns 3?
A managed object ID is a form of URI that uniquely identifies a managed object as residing within a particular persistent store.
It breaks down as:
protocol://persistent-store-uuid/entity-name/object-num
… because you can have many persistent stores with objects of the same entity stored in each, the ID for a managed object must include the store.
You save managedObjectIDs as attributes by converting them to their URI representation and setting the attribute to the resulting URL.
Why should it return 3? objectID returns a NSManagedObjectID which has to uniquely identify your object.

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"])

how to create a auto-incremented attribute in xcode managed object model

Hey, what i want to do is to make a int that will be the ID of the entity and auto increment itself whenever a new entity is added (just like a SQL identity property). Is this possible? i tried using indexed (checked on attribute) however there is no description to what indexed even does.
EDIT:
I am adding annotations to a map, when you click the pin the annotationview with a chevron shows up. Now when you click this button i would like to load an associated picture. However the only way i know how to link the picture to this button is to give the picture a unique id, and then set the button.tag to this id and then load based on the button.tag.
This kind of concept is contrary to the principles of Core Data - the idea is that you're managing sets of entities with properties, not rows in a database or other things that need to be uniqued. (If you're using the SQLite store, Core Data will create an ID for you behind the scenes, but you can't access it.)
You should probably reconsider (or at least give more details about) the problem you're trying to solve, because as it stands, Core Data will not let you autoincrement a variable.
If you absolutely must, you can manually increment on insert by having some NSNumber ID field on your entity, then every time you insert a new entity, get the existing entities sorted by that ID and limited to one result (using a NSFetchRequest with various options), grab that entity's ID, add one, and set it as the new entity's ID. It's a lot of work, though, and probably error-prone.
Edit: Based on the extra information, I'd say rather than trying to autoincrement an ID yourself, find some other guaranteed-unique property of the annotation and either use that directly or write a hash function that uses it to generate your unique ID. For example, use the latitude & longitude to build a single integer that uniquely represents that point within your system. Other than that, there's no way around having to increment the ID yourself.
I agree that this is a sticky problem - I haven't ever come across something like this in Core Data before, and I can see where autoincrementing might be useful :)
This is the simplest way, but takes some effort.
Create an "index" attribute in your Entity. Make it a String
When you create a new one, generate a GUID using CFUUIDCreate() and CFUUIDCreateString()
Assign the GUID to the "index" attribute
Voila, you now have a nearly-perfect unique ID, ready to use for caching locally and using as needed
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef uuidStringRef = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
NSString* guidString = [NSString stringWithString:(__bridge NSString*)uuidStringRef];

NSMutableArray of NSString in CoreData(iPhone

I have a class, which describe an object for parsing XML. This class contains NSStrings and NSMutableArrays of NSStrings.I want to store parsed data using CoreData. How should I write CoreData model to store such objects if there is no such data type like NSMutableArray? Is there any way?
You can create two entities, I'll call them Array and String. Array has one relationship, strings, which is a one-to-many relationship with the String entity. The String entity then has one attribute, I'll call it string too, which actually is a string and contains the value you need. This will allow you to store them as a set, if the order is important add another attribute to the String entity called order and make it a number.
There isnt an array data type, but u can box the string in a core data object (lets call it A for the remainder of the post). Then in the object (B) which you want to have the array of string (that persists) in just make a to-many relationship with the object A which contains the string, then youll have a Set of string on the object B which you can turn into an array and do with what you like. hope that helps