82
votes

This may seem stupid, but I still couldn't figure out how to mark a attribute as a primary key in the xcdatamodel file. My persistent storage is sqlite file. Can anyone help me?

In that case, how can I "validate" a ID to be unique? Should I write a validation method or something?

7

7 Answers

94
votes

Your options are:

  • Use -[NSManagedObject objectID]. Note that this ID is temporary until either the object is saved for the first time or you call -[NSManagedObjectContext obtainPermanentIDsForObjects:error:]
  • Use the CFUUID family of functions to generate a UUID for each object in your -awakeFromInsert method
  • Create your own primary key-like system that stores an integer in your model and increments it with the creation of each object

There is no good way to validate that a property is unique. The closest you'll get is to ensure it is unique at creation time, and then implement a custom setter method that stops anyone ever changing the ID.

46
votes

Keep in mind that Core Data is an object-graph persistence framework, not a database. Things like primary keys are abstracted away because they depend on the implementation of the persistent store.

24
votes

Core Data makes its own primary key - you don't have to add one. You can retrieve it with

NSManagedObjectID *moID = [managedObject objectID];
14
votes

sometimes when hacking one needs the actual int of the primary key. here is how one can grab it:

NSManagedObjectID *yourManagedObjectID = [yourManagedObject objectID];
int yourManagedObject_PK = [[[[[yourManagedObjectID URIRepresentation] absoluteString] lastPathComponent] substringFromIndex:1] intValue];

despite CoreData being an object graph, if one looks at the CoreData generated SQLite database data, this way of grabbing the primary key of an NSManagedObject should not be a problem. ii have used CoreData and the low level sqlite3 C library together in the same code and passing primary keys from CoreData to sqlite3 for fetching records works just fine.

! if You intend to use this code in production, be aware of possible internal changes to the way the db primary key transforms into a URIRepresentation, it might brake Your code.

enjoy

0
votes

Without hacking NSManagedObjectID you can perform a fast check for your attribute before manage your remote data collection.

I've made an utility method, check it here

0
votes

A Swift Extension to retrieve the primary key

extension NSManagedObject {
    var primaryKey : String {
        guard objectID.uriRepresentation().lastPathComponent.count > 1 else { return "" }
        return objectID.uriRepresentation().lastPathComponent.substring(from: 1)
    }
}

And for String

extension String
{
    func substring(from : Int) -> String {
        guard self.count > from else { return "" }
        return String(self[self.index(self.startIndex, offsetBy: from)...])
     }
}
-3
votes

I'd rather use Time + the Class name as the unique identifier.