我真的很想避免使用NSManagedObjectID
作为将模型结构连接到其CoreData对象的方法。我的意思是这样的:
说我在CoreData中有一个Book
实体,然后有一个这样的模型结构代表我的模型层:
struct BookModel {
let name: String
...
let objectID: NSManagedObjectID // I need this to refer back to the entry in the database
}
我不喜欢这种方法。它使结构的工作变得乏味,例如,测试很烦人,因为我总是必须生成虚拟的objectIds或将BookModel.objectID
设为可选。
[我想拥有的是id
实体内类型为UUID
的Book
属性。这将很容易连接到结构,并且还允许结构在没有数据库的情况下正确存在:
struct BookModel {
let name: String
...
let id: UUID
...
func object() -> Book {
// Retrieve managed object using a fetch request with a predicate.
}
}
我注意到您实际上可以在实体中具有UUID
属性。但是,性能差异似乎很大。我创建了一个示例,尝试获取单个对象10000次。
[首先,我使用context
的object(with: NSManagedObjectID)
来获取它们。我将所有可能的objectId硬编码在一个数组中,并每次都随机传递一个。
然后,我使用带有NSPredicate
的简单获取请求,并通过了随机UUID。
执行时间差异很大:
使用ObjectID:0.015282376s
使用UUID:1.093346287s
但是,奇怪的是第一种方法实际上没有产生任何SQL查询(我使用启动参数-com.apple.CoreData.SQLDebug 4
记录了它们)。这可以解释速度,但不能解释为什么它根本不需要与数据库进行通信。
我进行了一些研究,但无法真正弄清楚object(with: NSManagedObjectID)
在幕后的实际作用。
这是否意味着使用“自定义” UUID
属性不是一个好主意?我非常感谢对此有任何见解!
我不会依赖您代码中的NSManagedObjectID
。它使您的代码依赖于Apple的数据库实现,该实现随时可能更改,并且不会使您的应用程序对将来的更改具有弹性。
通过示例,您将无法使用新的NSPersistentCloudKitContainer
。它不支持NSManagedObjectID
:请参见https://developer.apple.com/documentation/coredata/mirroring_a_core_data_store_with_cloudkit/creating_a_core_data_model_for_cloudkit
代替硬编码NSManagedObjectID
,您最好按照您的建议为实体提供唯一的UUID。这可能会或可能不会影响性能,但是从长远来看,您的状况会更好,因为基础核心数据库技术将发生变化。