首页 > 解决方案 > 是否可以在 NSFetchedResultsController 的 NSSortDescriptor 中使用 UUID?

问题描述

当使用in 的UUID属性时,应用程序会崩溃:NSManagedObjectNSFetchedResultsController

-[__NSConcreteUUID compare:]:无法识别的选择器发送到实例

当内容NSFetchedResultsController.fetchedObjects改变时,而不是在第一次加载时。首次加载时,对象按 UUID 正确排序。

这就是我创建的方式NSFetchedResultsController

let fetchRequest: NSFetchRequest<MyObject> = MyObject.fetchRequest()
fetchRequest.sortDescriptors = [
    NSSortDescriptor(key: #keyPath(MyObject.uuid), ascending: true),
]

fetchRequest.predicate = NSPredicate(format: "%K == %@", #keyPath(MyObject.tag), tag)

let controller = NSFetchedResultsController(fetchRequest: fetchRequest,
                                            managedObjectContext: context,
                                            sectionNameKeyPath: nil,
                                            cacheName: nil)
controller.delegate = self
    
do {
    try controller.performFetch()
} catch {
    fatalError("###\(#function): Failed to performFetch: \(error)")
}

为了创建NSManagedObjectMyObject在上面的代码中),我使用模型编辑器添加了一个带有UUID类型的字段“uuid”。

看起来Core Data在SQL级别按UUID排序没有问题,但是在加载数据并尝试在内存中保持排序之后,它尝试以某种方式调用compareon _NSConcreteUUID,这作为方法不存在。此方法可以通过 UUID 的字节或字符串比较来实现。

失败的尝试:

也许有一种解决方法Transformable,可以让它从 SQL 端的本机 UUID 类型中受益,但仍然可以在内部使用NSFetchedResultsController

标签: iosswiftcore-datansfetchedresultscontrollernssortdescriptor

解决方案


不,不可能使用UUID属性对 Core Data 结果进行排序。如果要将 UUID 用于排序,则需要将其转换为字符串。

Core Data 在获取时实际上并没有对 UUID 进行排序。-com.apple.CoreData.SQLDebug 4如果您通过在 Xcode 的构建方案中添加参数来打开 Core Data SQLite 调试,您可以看到这一点。当您对时间戳等数字属性进行排序时,调试输出会包含一个 SQLORDER BY子句

CoreData: sql: SELECT 0, t0.Z_PK FROM ZEVENT t0 ORDER BY t0.ZTIMESTAMP DESC

如果您尝试使用UUID属性,则没有ORDER BY子句。Core Data 只是忽略了排序描述符。它不会崩溃,但也不会对结果进行排序。

我不确定这是为什么,因为使用sqlite3命令行工具打开 Core Data 创建的 SQLite 文件显示 UUID 属性表示为 SQLiteBLOB字段。SQLite 可以排序BLOB,即使这样做通常没有意义。

我建议向 Apple 提交错误。我不知道他们会怎么想这应该如何工作,但它绝对不应该忽略排序描述符并且不打印某种控制台消息。


推荐阅读