UITableView结合UISearchBar按关键词匹配数量排序的搜索实现求助
解决方案
核心逻辑
- 先对输入的搜索文本做预处理:拆分关键词、过滤空串、统一转小写
- 过滤阶段保留所有匹配至少1个关键词的记录
- 排序阶段为每条记录计算匹配到的关键词数量,按该数量降序排列,匹配数越高排越靠前
- 可选优化:将逗号分隔的tags拆分为独立标签集合,避免子串误匹配(比如标签
doggy不会被关键词dog误命中)
修正后完整代码
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { print("\(searchText)") // 空搜索直接返回原始数据,提前退出避免多余计算 guard !searchText.isEmpty else { filteredStorage = originalStorage1 tblView.reloadData() return } // 预处理搜索关键词:拆分、去空、转小写 let searchKeywords = searchText.components(separatedBy: " ") .filter { !$0.isEmpty } .map { $0.lowercased() } // 过滤逻辑:保留匹配至少1个关键词的记录 filteredStorage = originalStorage1.filter { obj in guard let tagsStr = obj["tags"] as? String else { return false } // 可选优化:将tags拆分为独立标签集合,避免子串误匹配,可替换下面的判断逻辑 /* let tagSet = Set(tagsStr.components(separatedBy: ",") .map { $0.trimmingCharacters(in: .whitespaces).lowercased() }) return searchKeywords.contains { tagSet.contains($0) } */ // 原逻辑保留,和你之前的过滤规则一致 let lowerTags = tagsStr.lowercased() for keyword in searchKeywords { if lowerTags.contains(keyword) { return true } } return false } // 排序逻辑:按匹配关键词数量降序排列 filteredStorage.sort { obj1, obj2 in // 计算obj1的匹配数 let matchCount1: Int if let tags1 = obj1["tags"] as? String { let lowerTags1 = tags1.lowercased() matchCount1 = searchKeywords.filter { lowerTags1.contains($0) }.count } else { matchCount1 = 0 } // 计算obj2的匹配数 let matchCount2: Int if let tags2 = obj2["tags"] as? String { let lowerTags2 = tags2.lowercased() matchCount2 = searchKeywords.filter { lowerTags2.contains($0) }.count } else { matchCount2 = 0 } // 匹配数高的排前面,若匹配数相同可自定义其他排序规则,比如按标签字符串字典序 return matchCount1 > matchCount2 } tblView.reloadData() }
关键修改说明
- 空搜索判断提前到逻辑最开头,减少不必要的过滤、排序计算
- 搜索关键词新增空值过滤,避免用户输入连续空格产生无效关键词
- 重写排序逻辑:分别计算两条记录的匹配关键词数量,直接比较匹配数实现降序排列,完全符合多关键词匹配度排序规则
- 补充了标签拆分的优化方案,避免原逻辑中子串匹配导致的误命中问题,可根据业务需求选择是否启用
内容的提问来源于stack exchange,提问作者Dhruv Rajpurohit
相关产品推荐
相关产品推荐

