按翻译后的属性对 Core-Data 对象进行排序
Sort Core-Data objects by translated properties
我的应用程序最近进行了本地化,现在我遇到了 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), ascending: true, 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
是一个字符串,是用来排序sections的属性。
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?
}
现在我需要使用这个 属性 的本地化版本。
我考虑过使用 replace/override NSString.localizedCompare(_:)
使用 NSLocalizedString 而不是字符串本身的方法进行 NSString 扩展,但我想我无法将它暴露给Objective-C 运行时(我得到“不支持的排序描述符”)。然后我想也许在实体扩展中添加一个计算的 属性,这将 return NSLocalizedString,例如 Category.translatedTypeSection 但我得到“由于未捕获的异常 'NSInvalidArgumentException' 而终止应用程序”,原因: 'keypath translatedTypeSection not found in entity Category'").
最后,我认为 会起作用,因为 OP 有一个非常相似的问题,但我无法将其转换为 Swift。
TL;DR
我的核心数据实体有一个typeSection
属性,这是一个预定义(非用户输入)英文字符串,用于排序部分。
既然该应用程序已本地化为其他语言,我需要根据此 属性 的翻译版本而不是数据库中记录的基本语言版本进行排序。
这与将您的代码公开给 ObjC 或翻译代码无关。您遇到麻烦是因为当您将 Core Data 与 SQLite 一起使用时,排序描述符在 SQLite 中执行。 ObjC 和 Swift 代码都不能用于排序,只能转换为 SQLite 排序规则的表达式。这就是“不受支持的排序描述符”的意思,它是框架告诉你它不能将该描述符转换成在 SQLite.
中运行的东西
找不到键路径错误的发生是因为,虽然排序描述符对于 SQLite 是可接受的,但它只适用于持久存储中存在的键。 SQLite 中不存在计算属性,所以发生错误是因为,在 SQL 术语中,您试图按那里不存在的列进行排序。
您 link 的答案与您的代码有重大差异。您正在尝试使用排序描述符作为提取的一部分,这需要一个可以在 SQLite 中工作的排序描述符。 linked 答案执行提取时根本没有排序描述符。然后它在内存中对结果进行排序。您也可以这样做,并且您尝试过的任何一种方法都应该有效,因为这两种方法都适用于对内存中的数组进行排序。
我的应用程序最近进行了本地化,现在我遇到了 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), ascending: true, 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
是一个字符串,是用来排序sections的属性。
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?
}
现在我需要使用这个 属性 的本地化版本。
我考虑过使用 replace/override NSString.localizedCompare(_:)
使用 NSLocalizedString 而不是字符串本身的方法进行 NSString 扩展,但我想我无法将它暴露给Objective-C 运行时(我得到“不支持的排序描述符”)。然后我想也许在实体扩展中添加一个计算的 属性,这将 return NSLocalizedString,例如 Category.translatedTypeSection 但我得到“由于未捕获的异常 'NSInvalidArgumentException' 而终止应用程序”,原因: 'keypath translatedTypeSection not found in entity Category'").
最后,我认为
TL;DR
我的核心数据实体有一个typeSection
属性,这是一个预定义(非用户输入)英文字符串,用于排序部分。
既然该应用程序已本地化为其他语言,我需要根据此 属性 的翻译版本而不是数据库中记录的基本语言版本进行排序。
这与将您的代码公开给 ObjC 或翻译代码无关。您遇到麻烦是因为当您将 Core Data 与 SQLite 一起使用时,排序描述符在 SQLite 中执行。 ObjC 和 Swift 代码都不能用于排序,只能转换为 SQLite 排序规则的表达式。这就是“不受支持的排序描述符”的意思,它是框架告诉你它不能将该描述符转换成在 SQLite.
中运行的东西找不到键路径错误的发生是因为,虽然排序描述符对于 SQLite 是可接受的,但它只适用于持久存储中存在的键。 SQLite 中不存在计算属性,所以发生错误是因为,在 SQL 术语中,您试图按那里不存在的列进行排序。
您 link 的答案与您的代码有重大差异。您正在尝试使用排序描述符作为提取的一部分,这需要一个可以在 SQLite 中工作的排序描述符。 linked 答案执行提取时根本没有排序描述符。然后它在内存中对结果进行排序。您也可以这样做,并且您尝试过的任何一种方法都应该有效,因为这两种方法都适用于对内存中的数组进行排序。