2017-03-29 46 views
0

我对核心数据的简单Person实体,我注意到,增加的数据时,每行是自动生成的唯一PK称为的objectID核心数据使用自动生成的主键PK

我希望检索使用记录的objectID,但我收到以下错误:

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) 
     } 

    } 

} 

调用上面的:

//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!)") 
     } 

    } 
} 

回答

0

objectIDNSManagedObject的一个属性,但不是持久性存储中字段的名称或实体描述的一部分。你不能在谓词中使用它,因为它不能用作过滤器。 主存储中对应于对象ID的字段,但它也不可用于获取请求,因为这不是核心数据打算如何使用的字段。

如果你想要一个带有核心数据的主键,你需要自己创建它。或者,如果您确实需要SQL风格编码,请直接使用SQLite并且不要涉及到Core Data。

+0

有趣的是,最好忽略主键并改用自己的值。 –

+0

是的。核心数据通常通过关系维护参照完整性。这些将由内部私钥进行备份,但这是一个实现细节。使用核心数据时,请小心不要过多地考虑SQL,因为这不是一回事。 –

1

您可以使用谓词"self == %@", objectID来获取objectID。 objectID是managedObject的属性,其类型为NSManaged​Object​ID而不是Int。一般来说,最好创建和管理你自己的objectId。我通常使用UUID字符串。

+1

但是,这需要一个NSManaged Object ID,并且不会像问题中那样与'let personID:Int = 2'一起使用。 –

+0

这使你想知道他们为什么为你创建主键,但不让你访问它。似乎是鼓励我们打破参照完整性的规则。 –