53

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?

pkamb
  • 33,281
  • 23
  • 160
  • 191
WoodenKitty
  • 6,521
  • 8
  • 53
  • 73

4 Answers4

114

-[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.

Community
  • 1
  • 1
Barry Wark
  • 107,306
  • 24
  • 181
  • 206
  • 38
    I wish I could give you another plus for 'Core Data is not a database'. – Abizern Jun 16 '11 at 23:47
  • 10
    There are common use cases where you need to grab an object by its id -- passing data from a table view cell selection to a detail view controller comes to mind. You could just pass the object itself, but often you don't want to do that if you are using a different context in the detail VC. – memmons Oct 28 '12 at 03:43
  • 1
    @Michael: Exactly. What is the best practice for doing this? – Noah Dec 19 '13 at 06:33
  • 2
    @Noah passing objectIDs is one of the 2 best practices [according to Apple](https://developer.apple.com/library/mac/documentation/cocoa/conceptual/coredata/articles/cdConcurrency.html). – Shai Feb 04 '14 at 14:57
  • 1
    How does one manage objectIDs in a server->client situation where syncing is necessary? – Jason Foglia Nov 15 '16 at 22:46
  • You don’t. Treat managedObjectID’s as local to the store and pass the data between client and server. Add your own ID field as necessary. CoreData uses SQLite which is an embedded database, not a distributed one. – user965972 Aug 21 '21 at 21:31
46

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.

pkamb
  • 33,281
  • 23
  • 160
  • 191
Donnit
  • 1,217
  • 12
  • 19
  • 1
    exactly! the same problem. needed to send the server this id with entity details to make an entry into remote mySQL and then in response, get the server generated unique id with the same objectID. get the object form objectId and store the server id in it. – Amogh Talpallikar Oct 17 '12 at 20:13
  • Thank you for the nyc explanation and code… solved my problem.. :) – Ahmed Z. Dec 20 '13 at 05:05
  • @donnit, amogh So what do I do in a situation where I am saving content offsite, and then when I need to populate the server end to then be able to match Id's and update values? and also be able to add a new object if the id doesn't exist in the database. How would I accomplish that then? – Pavan Jan 25 '14 at 15:39
1

This is the way you can get the object id as String using Swift from a NSManagedObject:

entity.objectID.uriRepresentation().absoluteString
pableiros
  • 14,932
  • 12
  • 99
  • 105
0

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"])
M_Khater
  • 49
  • 4