问题描述
我的应用最近进行了本地化,现在我遇到了 NSSortDescriptor 和 Core Data 的问题。
基本上,我有一个对具有预定义英语属性的对象使用 NSSortDescriptor 的获取请求,现在我需要使用翻译版本进行排序。
当使用基本语言(英语)时,这有效:
func initTodayGrouped(delegate: NSFetchedResultsControllerDelegate) -> NSFetchedResultsController<Category> {
let request: NSFetchRequest<Category> = Category.fetchRequest()
request.predicate = nspredicate(format: "active == %d",true)
let sort = NSSortDescriptor(key: #keyPath(Category.title),ascending: true,selector: #selector(Nsstring.localizedCompare(_:)))
let sectionSort = NSSortDescriptor(key: #keyPath(Category.typeSection),selector: #selector(Nsstring.localizedCompare(_:)))
request.sortDescriptors = [sectionSort,sort]
let controller = NSFetchedResultsController(fetchRequest: request,managedobjectContext: managedContext,sectionNameKeyPath: #keyPath(Category.typeSection),cacheName: nil)
controller.delegate = delegate
return controller
}
Category
是我的核心数据实体,而字符串 Category.typeSection
是用于对节进行排序的属性。
extension Category {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Category> {
return NSFetchRequest<Category>(entityName: "Category")
}
@NSManaged public var active: Bool
@NSManaged public var color: String?
@NSManaged public var icon: String?
@NSManaged public var id: UUID?
@NSManaged public var index: Int16
@NSManaged public var subtitle: String?
@NSManaged public var title: String?
@NSManaged public var typeSection: String? // <-- HERE
@NSManaged public var events: NSSet?
}
现在我需要使用这个属性的本地化版本。
我想用一种方法来制作一个 Nsstring 扩展,该方法会替换/覆盖 Nsstring.localizedCompare(_:)
,它会使用 NSLocalizedString 而不是字符串本身,但我想我无法将它暴露给 Objective-C 运行时(我得到“不受支持的排序描述符”)。然后我想可能会在实体扩展中添加一个计算属性,它会返回 NSLocalizedString,如 Category.translatedTypeSection 但我得到“由于未捕获的异常‘NSinvalidargumentexception’而终止应用程序,原因:‘keypath translateTypeSection not found in entity Category’”) .
最后,我认为 this answer by Rob Napier 会起作用,因为 OP 有一个非常相似的问题,但我无法将其转换为 Swift。
TL;DR
我的核心数据实体有一个 typeSection
属性,它是一个预定义(非用户输入)英文字符串,用于对部分进行排序。
既然应用已本地化为其他语言,我需要对此属性的翻译版本而不是数据库中记录的基本语言版本进行排序。
解决方法
这不是将您的代码暴露给 ObjC 或翻译代码。您遇到了麻烦,因为当您将 Core Data 与 SQLite 一起使用时,排序描述符在 SQLite 中执行。 ObjC 和 Swift 代码都不能用于排序,只能使用可以转换为 SQLite 排序规则的表达式。这就是“不受支持的排序描述符”的意思,它是框架告诉您它无法将该描述符转换为在 SQLite 中运行的内容。
发生键路径未找到错误的原因是,尽管排序描述符对于 SQLite 是可以接受的,但它仅适用于存在于持久存储中的键。 SQLite 中不存在计算属性,因此发生错误是因为,在 SQL 术语中,您试图按不存在的列进行排序。
您链接的答案与您的代码有很大的不同。您正在尝试使用排序描述符作为提取的一部分,这需要一个可以在 SQLite 中工作的排序描述符。链接的答案在根本没有排序描述符的情况下执行提取。然后它在内存中对结果进行排序。您也可以这样做,您尝试过的任何一种方法都应该可行,因为这两种方法都适用于对内存中的数组进行排序。