是否可以在 NSFetchedResultsController 的 NSSortDescriptor 中使用 UUID?

Is it possible to use a UUID in an NSSortDescriptor for NSFetchedResultsController?

NSFetchedResultsController 中使用 UUID 属性 of NSManagedObject 时,应用程序崩溃:

-[__NSConcreteUUID compare:]: unrecognized selector sent to instance

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

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

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

失败的尝试:

也许有一个使用 Transformable 的变通方法可以让它从 SQL 端的本机 UUID 类型中获益,但在 NSFetchedResultsController 内部仍然可用?

不,无法使用 UUID 属性 对核心数据结果进行排序。如果要使用 UUID 进行排序,则需要将 UUID 转换为字符串。

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

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

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

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

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