0
votes

I have a simple Person entity in Core Data, I noticed that when adding data, each row is auto generated a unique PK called objectID

I wish to retrieve the records using the objectID but I am getting the following error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath objectID not found in entity < NSSQLEntity Person id=2 >'

func fetchPerson(withID personID: Int,
                 context: NSManagedObjectContext,
                 completion: @escaping ([Person]?) -> Void) {

    let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest()

    let predicate = NSPredicate(format: "\(#keyPath(Person.objectID)) == \(personID)")
    fetchRequest.predicate = predicate

    //perform aynchronous operation:
    context.perform {
        do {
            let persons = try fetchRequest.execute()
            //success - return array of persons
            completion(persons)
        } catch {
            //error - return nil
            completion(nil)
        }

    }

}

Calling the above :

//fetch person with specific id:
let personID: Int = 2
fetchPerson(withID: personID, context: persistentContainer.viewContext) { (persons: [Person]?) in
    if persons != nil {

        print("Fetching person with personID: \(personID)")
        for person in persons! {
            print("Person: \(person.objectID) - \(person.firstName!) \(person.lastName!)")
        }

    }
}
2

2 Answers

1
votes

You can fetch with objectID by using the predicate "self == %@", objectID. An objectID is property of a managedObject and its type is NSManaged​Object​ID not an Int. In general it is better to create and manage your own objectId. I generally use UUID strings.

0
votes

The objectID is a property of NSManagedObject but is not the name of a field in the persistent store or part of the entity description. You can't use it in predicates because it's not there to use as a filter. There is a field in the primary store that corresponds to the object ID, but it's also not available to fetch requests because that's not how Core Data is intended to be used.

If you want a primary key with Core Data, you need to create it yourself. Or if you really want SQL-style coding, use SQLite directly and don't get Core Data involved.