You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用NSPredicate基于自定义对象数组实现搜索?

刚好做过类似的需求,用NSPredicate来实现这种联系人搜索很合适,不过因为你的数据源是按section分组的二维数组,得先理清是要返回扁平化的结果还是保留section结构,下面给你两种实用的实现方式:

实现方案

1. 返回扁平化的搜索结果(一维数组)

如果不需要保留原有的section分组,只想拿到所有符合条件的WPH对象,可以先把二维数组转成一维,再用谓词筛选:

// 假设你的contactsWithSections是类里的私有变量
private var contactsWithSections = [[WPH]]()

func searchFlatContacts(with searchStr: String) -> [WPH] {
    // 把二维数组扁平化,得到所有联系人的一维数组
    let allContacts = contactsWithSections.flatMap { $0 }
    
    // 创建谓词:确保fName不为空,且前缀匹配搜索字符串(忽略大小写)
    let predicate = NSPredicate(format: "fName != nil AND fName BEGINSWITH[c] %@", searchStr)
    
    // 用谓词筛选符合条件的对象
    return allContacts.filter { predicate.evaluate(with: $0) }
}

2. 保留Section结构的搜索结果(二维数组)

如果需要保留原有的分组结构,只显示每个section里符合条件的联系人,可以遍历每个section单独筛选,再去掉空的section:

func searchSectionedContacts(with searchStr: String) -> [[WPH]] {
    let predicate = NSPredicate(format: "fName != nil AND fName BEGINSWITH[c] %@", searchStr)
    
    // 对每个section内的元素筛选,然后过滤掉没有匹配结果的空section
    return contactsWithSections.map { section in
        section.filter { predicate.evaluate(with: $0) }
    }.filter { !$0.isEmpty }
}

关键细节说明

  • 匹配规则调整:
    • 如果你需要的是前缀匹配(比如搜"al"只返回alex、alena这种以al开头的),用BEGINSWITH[c];
    • 如果你需要包含匹配(比如搜"le"能匹配alex、alena),把BEGINSWITH[c]换成CONTAINS[c];
    • 去掉[c]就会区分大小写,比如搜"Al"只会匹配首字母大写的对象。
  • 处理可选值:加上fName != nil是为了避免fName为nil的对象被误匹配,让筛选逻辑更严谨。
  • 为什么能用NSPredicate:因为WPH继承自NSObject,支持KVC访问属性,所以可以直接通过"fName"这种路径来构建谓词。

内容的提问来源于stack exchange,提问作者Harendra Tiwari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:00:13