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

UISearchController索引越界问题及WhatsApp群成员选择功能实现求助

我来帮你一步步解决这个问题,咱们先拆解核心问题和需求,逐个击破:

一、解决搜索时的Index Out Of Range崩溃

首先分析崩溃根源:你在didSelectRowAt里用了selectedUsers.index(of: cell.user)!的强制解包,如果因为状态不同步(比如重复点击、搜索状态下数据刷新)导致cell.user不在selectedUsers里,直接就会触发崩溃。另外,cell.user的可选性也可能带来隐患,咱们调整代码:

修复代码

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    guard let cell = tableView.cellForRow(at: indexPath) as? GroupRegistrationTableViewCell,
          let selectedUser = cell.user else { return }
    
    cell.added = !cell.added
    
    if cell.added {
        addRecipient(user: selectedUser)
    } else {
        // 安全获取索引,避免强制解包崩溃
        if let removeIndex = selectedUsers.index(of: selectedUser) {
            deleteRecipient(user: selectedUser, index: removeIndex)
        }
    }
}

// 同时优化cellForRowAt,直接用明确的user对象判断选中状态
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "GroupRegistrationTableViewCell") as! GroupRegistrationTableViewCell
    
    let targetUser: User
    if isFiltering() {
        targetUser = filteredUsers[indexPath.row]
    } else {
        targetUser = usersArray[indexPath.row]
    }
    
    cell.user = targetUser
    cell.added = selectedUsers.contains(targetUser) // 直接用确定的user对象判断,避免cell.user的可选问题
    return cell
}
二、确保selectedUsers数组无重复

当前addRecipient方法直接append用户,没有去重判断,会导致数组里出现重复项。咱们修改这个方法:

func addRecipient(user: User) {
    // 添加前先判断是否已存在,避免重复
    guard !selectedUsers.contains(user) else { return }
    selectedUsers.append(user)
}
三、彻底移除搜索栏的取消按钮

你现在在updateSearchResults里设置取消按钮隐藏,但第一次点击搜索栏时系统会默认显示,咱们换个更彻底的方式:

override func viewDidLoad() {
    super.viewDidLoad()
    self.fetchUsers()
    navigationItem.title = "GroupRegistration"
    navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
    
    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar
    searchController.searchBar.placeholder = "Search Members"
    searchController.hidesNavigationBarDuringPresentation = false
    
    // 关键:一开始就隐藏取消按钮
    searchController.searchBar.showsCancelButton = false
    // 监听搜索栏开始编辑事件,确保取消按钮不会弹出来
    searchController.searchBar.addTarget(self, action: #selector(searchBarDidBeginEditing), for: .editingDidBegin)
}

@objc private func searchBarDidBeginEditing() {
    searchController.searchBar.showsCancelButton = false
}
额外优化建议
  1. 异步加载用户的线程安全:
    Firebase的回调是在后台线程,更新UI必须切回主线程,同时搜索状态下要同步过滤结果:
func fetchUsers() {
    DatabaseReference.users(uid: currentUser.userUID).reference().child("follows").observe(.childAdded, with: { (snapshot) in
        DispatchQueue.main.async {
            let user = User(dictionary: snapshot.value as! [String:Any])
            self.usersArray.insert(user, at: 0)
            let indexPath = IndexPath(row: 0, section: 0)
            self.tableView.insertRows(at: [indexPath], with: .fade)
            
            // 如果当前在搜索状态,同步更新过滤列表
            if self.isFiltering() {
                self.filteredContentForSearchText(searchText: self.searchController.searchBar.text)
            }
        }
    })
}
  1. 优化搜索过滤方法:
    避免强制解包搜索文本,让代码更健壮:
func filteredContentForSearchText(searchText: String?, scope: String = "All") {
    guard let text = searchText, !text.isEmpty else {
        filteredUsers = usersArray
        tableView.reloadData()
        return
    }
    filteredUsers = usersArray.filter { $0.fullName.lowercased().contains(text.lowercased()) }
    tableView.reloadData()
}

func updateSearchResults(for searchController: UISearchController) {
    filteredContentForSearchText(searchText: searchController.searchBar.text)
    searchController.searchBar.showsCancelButton = false
}

这样修改后,你的三个需求都能完美满足,同时彻底解决搜索时的崩溃问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:20:42