Swift iOS开发:实现数组标签包含匹配的过滤逻辑
问题根因
你当前使用的$0.recipeTags! == [action.title]是数组全等判断,只有当食谱的recipeTags数组仅包含当前选中标签这一个元素时才会返回真,无法满足「标签数组包含选中标签即命中」的匹配规则,同时代码里多处强制解包可选值存在运行时崩溃风险。
修复方案
核心是将数组全等判断替换为contains成员检查,同时对可选值做安全解包:
- 替换过滤逻辑:用数组的
contains(_:)方法检查食谱标签列表是否包含当前选中的标签 - 移除所有强制解包:对
recipeTags、tagData这类可选值做安全校验,避免字段为空时闪退 - 补充菜单选中状态:记录当前选中的标签,让UIMenu弹出时能正确显示勾选态
核心过滤代码修改
把原来闭包里的过滤行替换为以下代码:
self.filteredData = self.recipeData.filter { recipe in // 空标签的食谱默认不命中任何标签筛选 guard let tags = recipe.recipeTags else { return false } return tags.contains(action.title) }
完整优化后的业务代码
var recipeData: [RecipeData] = [] var tagData: [TagData]? // 新增变量记录当前选中标签,用于菜单状态同步、筛选重置 var currentSelectedTag: String? func popupMenu() { var optionsArray = [UIAction]() let optionClosure = {(action: UIAction) in self.headerSearchTitle = action.title self.currentSelectedTag = action.title // 包含匹配过滤逻辑 self.filteredData = self.recipeData.filter { recipe in guard let recipeTags = recipe.recipeTags else { return false } return recipeTags.contains(action.title) } self.isSearching = true self.tableView.reloadData() } // 安全解包标签列表,避免tagData为空时崩溃 guard let customTags = self.tagData?.first?.customTags else { return } for tag in customTags { // 同步菜单选项的选中状态 let actionState: UIAction.State = tag == self.currentSelectedTag ? .on : .off let action = UIAction(title: tag, state: actionState, handler: optionClosure) optionsArray.append(action) } let optionsMenu = UIMenu(title: "Custom tags", options: .displayInline, children: optionsArray) // 记得将生成的menu绑定到对应触发控件,例如筛选按钮的menu属性 }
扩展说明
- 如果后续需要新增「全部分类」选项,只需要在标签数组最前面插入"全部"字符串,过滤逻辑里判断选中值为"全部"时,直接将
filteredData赋值为全量recipeData即可 - 如果后续要支持多标签筛选,只需要把存储选中值的变量改为数组类型,判断逻辑替换为「选中标签全部被食谱标签包含」(用
allSatisfy)或者「选中标签任意一个被食谱标签包含」(用contains(where:))即可
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

