考虑以下Realm模型:
class Fruit: Object {
@objc dynamic var name = ""
let localizations = List<Localization>()
/**
Returns the localized name of the fruit matching the preferred language of the app
or self.name if the fruit does not have a localization matching the user preferred language codes.
*/
var localizedName: String? {
guard !Locale.isPreferredLanguageDefaultAppLanguage else { return self.name }
let preferredLanguagesCodes = Locale.preferredLanguagesCodes
let localizations = preferredLanguagesCodes.compactMap({ languageCode in Array(self.localizations).filter({ $0.languageCode == languageCode }).first })
return localizations.first?.localizedName ?? self.name
}
}
class Localization: Object {
@objc dynamic var localizedName: String = ""
@objc dynamic var languageCode: String = ""
}
假设我的数据库中有2个水果(为简单起见,以JSON格式表示):
[
{
"name": "Apple",
"localizations": [
{
"localizedName": "Pomme",
"languageCode": "fr"
}
]
},
{
"name": "Banana",
"localizations": [
{
"localizedName": "Banane",
"languageCode": "fr"
}
]
}
]
现在,我想获取数据库中的所有水果,并按其localizedName
的字母顺序对其进行排序。
var localizedNameSortingBlock: ((Fruit, Fruit) -> Bool) = {
guard let localizedNameA = $0.localizedName, let localizedNameB = $1.localizedName else { return false }
return localizedNameA.diacriticInsensitive < localizedNameB.diacriticInsensitive
}
let sortedFruits = Array(Realm().objects(Fruit.self)).sorted(by: localizedNameSortingBlock)
如果我的设备的首选首选语言是“英语”,我会得到:
如果将其设置为“法语”:
这很简单,但是此解决方案有一个很大的不便之处:
通过将Results<Fruit>
集合转换为数组,我失去了通过Realm的通知令牌系统获取实时更新的能力。
问题是,我无法直接在Results集合上使用NSPredicate
进行排序,因为localizedName
属性是计算属性,因此被Realm忽略。
我考虑过将localizedName
的值直接写入name
对象的Fruit
属性中,但是这样做需要遍历所有水果并在用户更改名称时更改其名称。首选语言。必须有更好的方法。
所以我的问题是:
localizedName
对其进行排序,而又不会失去从Realm接收批量更新的功能?