如何制作正确过滤本地字符的 NSPredicate?

Posted

技术标签:

【中文标题】如何制作正确过滤本地字符的 NSPredicate?【英文标题】:How do I make an NSPredicate that filters local characters properly? 【发布时间】:2019-07-04 11:13:00 【问题描述】:

我的应用程序正在使用 Realm 数据库来存储许多项目。使用 SearchBar,我搜索(不区分大小写)可能已经存储在数据库中的项目(如果没有,它将被添加)。项目名称通常包含瑞典字符之一,我的问题是在搜索瑞典字符(å、ä 或 ö)时,过滤器也会通过“a”或“o”,即搜索“ä”结果在 a/A、å/Å 和 ä/Ä。

extension ItemsVC: UISearchResultsUpdating 

    func updateSearchResults(for searchController: UISearchController) 

        if isFiltering() 
            let predicate = NSPredicate(format: "name CONTAINS[cd] %@ AND NONE owners.name == %@", searchController.searchBar.text!, (category?.name)!)
            items = realm.objects(Item.self).filter(predicate).sorted(byKeyPath: "name", ascending: true)

            tableView.reloadData()
        
    

【问题讨论】:

CONTAINS[cd] 中的 d 表示变音符号不敏感。 CONTAINS[c] 是否给出了你想要的结果? 很遗憾没有。删除 d 也会删除特殊字符的不区分大小写。 @Stalle 你只删除了d 吗? 当然。似乎特殊的瑞典字符不被视为同一个的大写。 【参考方案1】:

这似乎是 Realm 的 filter 实现中的一个错误。如果您为包含相同对象的NSArray 提供相同的谓词,则这些谓词会返回正确的结果。

class Person: Object 
    @objc dynamic var name:String = ""


let people = stringsWithAccents.mapPerson(value: ["name":$0])
try realm.write 
    realm.add(people)


let namePredicate = NSPredicate(format: "name CONTAINS[c] %@", searchString)
let foundPeople = realm.objects(Person.self).filter(namePredicate)
print(foundPeople) // Results<Person> <0x7fec74c13060> ( [0] Person  name = á; )

print((people as NSArray).filtered(using: namePredicate)) // [Person  name = á;,Personn  name = Á;]

我在 RealmCocoa 的 GitHub 上opened an issue。

同时,作为一种解决方法,您可以手动检查小写和大写版本:

let customCaseInsentiveNamePredicate = NSPredicate(format: "name CONTAINS %@ OR name CONTAINS %@", searchString, searchString.uppercased())
print(realm.objects(Person.self).filter(customCaseInsentiveNamePredicate))

【讨论】:

以上是关于如何制作正确过滤本地字符的 NSPredicate?的主要内容,如果未能解决你的问题,请参考以下文章

核心数据 - NSPredicate 过滤掉工作不正确的空字符串

如何创建一个 NSPredicate 过滤给定范围内的所有字符,包括数字/数字?

使用 NSPredicate 过滤 NSArray 并找到相似的字符串

NSPredicate 没有正确过滤

使用 NSPredicate 过滤以数字或符号开头的字符串到 NSArray

带有特殊字符的 NSPredicate 过滤