我正在测试新的 SwifData 框架并使用新的 #Predicate 宏,并意识到它不支持不区分大小写的搜索。该宏不能与 lowercased() 方法或 localizedLowercase 属性一起使用,因此似乎无法像我们以前使用 NSPredicate 和 [c] 属性那样创建不区分大小写的谓词。
var predicate = #Predicate<Book> {
$0.title.localized().contains(search) }
错误:此谓词不支持 lowercased() 函数(来自宏“Predicate”)
我想知道是否有任何解决办法。 谢谢
更新 正如 Mikiko Jane 所指出的,这仅适用于数组的过滤谓词,而不是直接适用于
@Query
。
我尝试使用
@Transient
字段使其动态小写
@Transient
var nameNormalized: String {
name.lowercased()
}
谓词无法看到瞬态属性,因为我认为它只查找持久存在数据库中的内容。
我认为当前唯一的解决方案是创建一个每当第一个字段更新时更新的字段。为了拥有适当的搜索功能,需要大量的开销和样板代码。这似乎明显违背了 SwiftData 的目标。
原答案
我已经尝试过这个,尝试了很多解决方案,但我可能找到了一种进行不区分大小写比较的方法。在 SwiftData SampleTrips 示例项目中我更改了
let filteredList = try? trip.bucketList.filter(#Predicate { item in
item.title.contains(searchText) && tripName == item.trip?.name
})
至:
let filteredList = try? trip.bucketList.filter(#Predicate { item in
return item.title.localizedLowercase.contains(searchText.localizedLowercase) && tripName == item.trip?.name
})
这似乎有效。看来宏支持
localizedLowercase
但不支持 lowerCased()
新的
Predicate
宏与 localizedStandardContains(_:)
函数配合得很好。
这是进行用户级字符串搜索的最合适的方法,类似于系统中通常进行的搜索方式。 搜索可识别区域设置,不区分大小写和变音符号。所应用的搜索选项的确切列表可能会随着时间的推移而改变。
用途:
let userInput = "foo bar"
let predicate = #Predicate<Book> { $0.title.localizedStandardContains(userInput) }