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

Swift中UITableView动态数据搜索功能失效问题求助

我帮你排查出了几个导致搜索过滤功能失效的核心问题,咱们一步步来修复:

1. UISearchBar代理方法签名错误且被私有化

你当前的代理方法用了旧版Swift语法,还加了private修饰符,这会导致系统无法正确调用这些方法。请把所有搜索相关的代理方法改成Swift 3+的标准写法,并且去掉private:

// 替换你原来的private代理方法
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    isSearching = true
}

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    isSearching = false
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    isSearching = false
    searchBar.text = "" // 清空搜索框
    menuTableView.reloadData() // 刷新表格回到原始数据
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    isSearching = false
    searchBar.resignFirstResponder() // 收起键盘
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    // 搜索逻辑我们后面再调整
}

2. 数据存储逻辑混乱,dishNameArray初始化时机错误

你现在是在cellForRowAt方法里往dishNameArray添加数据,这会导致重复添加,而且只有当cell被复用时才会有数据,完全不符合逻辑。正确的做法是:在你从服务端拿到ResMenuService.instance.categoryModelInstance之后,一次性把所有分类名存入数组,比如在数据加载完成的回调里添加:

// 假设你在获取服务端数据成功后调用这个方法
func setupDishData() {
    dishNameArray = ResMenuService.instance.categoryModelInstance.map { $0.categoryName }
}

3. cellForRowAt里的逻辑覆盖了搜索结果

当isSearching为true时,你先设置了搜索结果的文本,但后面又直接用原始模型覆盖了这个值,导致永远显示原始数据。更合理的是直接过滤整个模型数组,而不是只存名字,这样cell可以直接使用模型的完整数据:

首先把filteredData改成模型数组类型(替换原来的var filteredData = [String]()):

// 这里的CategoryModel是你对应ResMenuService中categoryModelInstance的模型类名
var filteredCategoryModels = [CategoryModel]()

然后修改搜索方法的逻辑:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    guard let searchText = searchBar.text, !searchText.isEmpty else {
        filteredCategoryModels.removeAll()
        isSearching = false
        menuTableView.reloadData()
        return
    }
    
    // 根据分类名过滤模型数组
    filteredCategoryModels = ResMenuService.instance.categoryModelInstance.filter {
        $0.categoryName.lowercased().contains(searchText.lowercased())
    }
    
    isSearching = !filteredCategoryModels.isEmpty
    menuTableView.reloadData()
}

接着调整numberOfRowsInSection的逻辑:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if tableView == menuTableView{
        if isSearching{
            return filteredCategoryModels.count
        }
        return ResMenuService.instance.categoryModelInstance.count
    } else{
        return AllReviewsService.instance.allReviewsModel.count
    }
}

最后修复cellForRowAt的逻辑,确保搜索状态下使用过滤后的模型:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if tableView == menuTableView{
        let cell = menuTableView.dequeueReusableCell(withIdentifier: "menuCell", for: indexPath) as! RestaurantMenuTableViewCell
        
        // 选择当前要使用的模型
        let currentModel: CategoryModel
        if isSearching {
            currentModel = filteredCategoryModels[indexPath.row]
        } else {
            currentModel = ResMenuService.instance.categoryModelInstance[indexPath.row]
        }
        
        // 设置cell数据
        cell.dishTitleLbl.text = currentModel.categoryName
        cell.cardView.layer.cornerRadius = 5
        cell.selectionStyle = .none
        
        return cell
    } else {
        // 评论cell的逻辑保持不变
        let cell = reviewTableView.dequeueReusableCell(withIdentifier: "reviewCell", for: indexPath) as! AllReviewsTableViewCell
        cell.nameLbl.text = AllReviewsService.instance.allReviewsModel[indexPath.row].name
        cell.descriptionLbl.text = AllReviewsService.instance.allReviewsModel[indexPath.row].description
        cell.timeLbl.text = AllReviewsService.instance.allReviewsModel[indexPath.row].time
        cell.ratingView.rating = Double(AllReviewsService.instance.allReviewsModel[indexPath.row].rating)
        cell.backgroundColor = UIColor.clear
        cell.selectionStyle = .none
        return cell
    }
}

4. 额外优化:确保搜索栏显示取消按钮

在viewDidLoad里添加一行代码,让搜索栏显示取消按钮,方便用户退出搜索状态:

searchBar.showsCancelButton = true

5. 修复点击事件的模型获取逻辑

在tableView(_:didSelectRowAt:)方法里,也要对应调整搜索状态下的模型获取逻辑,确保点击搜索结果时能拿到正确的模型数据:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if tableView == menuTableView{
        let selectedModel: CategoryModel
        if isSearching {
            selectedModel = filteredCategoryModels[indexPath.row]
        } else {
            selectedModel = ResMenuService.instance.categoryModelInstance[indexPath.row]
        }
        
        // 后续使用selectedModel来获取数据,比如minimumSpending等
        let minimumSpending = String(ResMenuService.instance.restaurntDetailModelInstance[indexPath.row].minimumSpending)
        UserDefaults.standard.set(minimumSpending, forKey: "minimumSpending")
        UserDefaults.standard.synchronize()
        
        let categoryModel = ResMenuService.instance.categoryModelInstance
        let subCategoryModel = selectedModel.subCategories
        let AddonCategoryModel = subCategoryModel[0].items[0].addonCategory
        
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "RestaurantMenuDetailVC") as! RestaurantMenuDetailVC
        vc.categoryModel = categoryModel
        vc.subCategoryModel = subCategoryModel
        vc.AddonCategoryModel = AddonCategoryModel
        self.navigationController?.pushViewController(vc, animated: true)
    } else{
        print("Hello")
    }
}

做完这些修改后,你的搜索过滤功能应该就能正常工作了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:36:58