【问题标题】:Sort Core-Data objects by translated properties按翻译的属性对核心数据对象进行排序
【发布时间】:2021-02-26 17:17:55
【问题描述】:

我的应用最近进行了本地化,现在我遇到了 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 是一个字符串,是用于对部分进行排序的属性。

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.localizedCompare(_:) 的方法制作一个 NSString 扩展,该方法将使用 NSLocalizedString 而不是字符串本身,但我认为我无法将它暴露给 Objective-C 运行时(我得到“不支持的排序描述符”)。然后我想可能会在实体扩展中添加一个计算属性,这将返回 NSLocalizedString,如 Category.translatedTypeSection 但我得到“由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'keypath translateTypeSection not found in entity Category'”) .

最后,我认为this answer by Rob Napier 会起作用,因为 OP 有一个非常相似的问题,但我无法将其翻译成 Swift。


TL;DR

我的核心数据实体有一个typeSection 属性,这是一个预定义(非用户输入)英文字符串,用于对部分进行排序。

既然应用程序已本地化为其他语言,我需要对该属性的翻译版本而不是数据库中记录的基本语言版本进行排序。

【问题讨论】:

    标签: swift core-data nsfetchedresultscontroller nssortdescriptor nslocalizedstring


    【解决方案1】:

    这不是将您的代码暴露给 ObjC 或翻译代码。您遇到了麻烦,因为当您将 Core Data 与 SQLite 一起使用时,排序描述符在 SQLite 中执行。 ObjC 和 Swift 代码都不能用于排序,只能使用可以转换为 SQLite 排序规则的表达式。这就是“不支持的排序描述符”的意思,它是框架告诉你它不能将该描述符转换为在 SQLite 中运行的东西。

    发生键路径未找到错误的原因是,尽管排序描述符对于 SQLite 是可接受的,但它仅适用于持久存储中存在的键。 SQLite 中不存在计算属性,因此会发生错误,因为在 SQL 术语中,您尝试按不存在的列进行排序。

    您链接的答案与您的代码有很大的不同。您正在尝试使用排序描述符作为提取的一部分,这需要一个可以在 SQLite 中工作的排序描述符。链接的答案在根本没有排序描述符的情况下执行提取。然后它对内存中的结果进行排序。您也可以这样做,并且您尝试过的任何一种方法都应该有效,因为这两种方法都适用于对内存中的数组进行排序。

    【讨论】:

    • 啊,我现在明白错误了,谢谢,但我还想不出解决办法。因为我在NSFetchedResultsController 上使用sectionNameKeyPath,所以我不知道如何在内存中进行这种排序。这是否意味着我必须在不使用sectionNameKeyPath 的情况下获取结果,然后对其进行排序,例如在控制器委托中?我不知道该怎么做。
    • 对不起,汤姆,但我无法解决这个问题。这是否意味着我必须停止使用 NSFetchedResultsController,而是做一个简单的 fetch 然后自己排序?当然,我可以这样做,但是当对象更改时,我会丢失控制器提供的自动更新,对吧?在这种情况下,我无法设想解决方案。
    • 要继续使用获取的结果控制器,您需要使用 Core Data 存储翻译,以便您可以将它们用作获取请求的一部分。为翻译添加一个新属性,然后在持久存储中运行,在您需要的任何地方添加翻译后的字符串。否则,您必须删除 fetched results 控制器并编写自己的代码来管理 UI 和 Core Data 之间的关系。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 2011-07-29
    相关资源
    最近更新 更多