UITableView内嵌UICollectionView:选中状态传递与行显隐处理问询
解决方案:传递选中事件并控制TableView行显隐
嘿,我来帮你搞定这个问题!核心就是要让内嵌UICollectionView的TableViewCell,把选中的答案传递给TableView所在的ViewController,然后由VC判断哪些行需要隐藏,最后刷新TableView生效。下面是两种最实用的实现方式:
方案一:用闭包传递选中事件(推荐,简单直接)
步骤1:修改内嵌CollectionView的TableViewCell
首先找到你的那个带UICollectionView的TableViewCell类(比如你代码里的FormExpenseTypeCell或者对应typeId的目标cell),给它添加一个闭包属性,用来传递选中的答案:
// 替换成你实际的cell类名,比如FormExpenseTypeCell class YourCollectionEmbeddedCell: UITableViewCell { // 你已有的属性:optionsCollectionView、selectedItem等 var selectedItem: String? // 添加闭包属性,用于传递选中结果 var onOptionSelected: ((String?) -> Void)? // 你的collectionView选中方法修改如下 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let cell = collectionView.cellForItem(at: indexPath) as? OptionsCollectionViewCell else { return } let selectedText = cell.itemButton.titleLabel?.text selectedItem = selectedText // 调用闭包,把选中的值传出去 onOptionSelected?(selectedText) } }
步骤2:在ViewController中接收事件并控制行显隐
在你的cellForRowAt方法里,初始化目标cell时设置闭包,处理选中后的逻辑,同时维护一个变量记录是否需要隐藏目标行:
// 在ViewController里添加变量,记录是否隐藏问题3 private var shouldHideQuestion3 = false func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if sortedFixedContentType.count != 0 { let item = sortedFixedContentType[indexPath.row] switch item.typeId { // 保留你其他case的代码不变 case "39": // 假设这个是带CollectionView的cell对应的typeId let cell = tableView.dequeueReusableCell(withIdentifier: "FormExpenseTypeCell", for: indexPath) as! FormExpenseTypeCell // 设置闭包,处理选中事件 cell.onOptionSelected = { [weak self] selectedAnswer in guard let self = self else { return } // 这里根据实际逻辑判断:比如当前cell是问题2,选中"No"则隐藏问题3 if indexPath.row == 1 { // 替换成你问题2的实际行索引或判断条件 self.shouldHideQuestion3 = (selectedAnswer == "No") // 刷新TableView,让行显隐生效 self.tableView.reloadData() } } return cell; // 其他case代码不变 default: let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! BaseFormCell cell.idLabel.text = item.htmlType return cell } } else { let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! BaseFormCell cell.idLabel.text = "" return cell } }
步骤3:控制行的显隐
实现heightForRowAt方法,根据shouldHideQuestion3的值控制目标行的高度:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { // 判断是否是需要隐藏的行(比如问题3的行) if indexPath.row == 2 && shouldHideQuestion3 { // 替换成问题3的实际行索引 return 0 // 高度设为0实现隐藏 } // 其他行返回自动高度或固定高度 return UITableView.automaticDimension }
或者你也可以用willDisplay方法设置cell的isHidden属性:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { if indexPath.row == 2 && shouldHideQuestion3 { cell.isHidden = true } else { cell.isHidden = false } }
方案二:用代理模式传递事件(适合复杂场景)
如果你的表单有多个类似的依赖问题,代理模式会更清晰:
步骤1:定义代理协议
protocol OptionSelectionDelegate: AnyObject { func didSelectOption(_ option: String?, from cell: UITableViewCell) }
步骤2:修改TableViewCell添加代理属性
class YourCollectionEmbeddedCell: UITableViewCell { weak var delegate: OptionSelectionDelegate? var selectedItem: String? func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let cell = collectionView.cellForItem(at: indexPath) as? OptionsCollectionViewCell else { return } let selectedText = cell.itemButton.titleLabel?.text selectedItem = selectedText // 通知代理 delegate?.didSelectOption(selectedText, from: self) } }
步骤3:ViewController遵守代理协议
class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, OptionSelectionDelegate { private var shouldHideQuestion3 = false func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // ...其他代码不变 case "39": let cell = tableView.dequeueReusableCell(withIdentifier: "FormExpenseTypeCell", for: indexPath) as! FormExpenseTypeCell cell.delegate = self // 设置代理 return cell // ...其他代码 } // 实现代理方法 func didSelectOption(_ option: String?, from cell: UITableViewCell) { guard let indexPath = tableView.indexPath(for: cell) else { return } // 判断当前cell对应的问题,比如问题2 if indexPath.row == 1 { shouldHideQuestion3 = (option == "No") tableView.reloadData() } } }
额外提示
- 用
[weak self]避免循环引用,防止内存泄漏 - 如果有多个依赖问题,建议维护一个字典(比如
[String: String])来记录每个问题的选中答案,key可以用问题的typeId或者索引,这样判断行显隐时更灵活 - 刷新TableView时,也可以用
reloadRows(at:with:)只刷新需要变化的行,提升性能:tableView.reloadRows(at: [IndexPath(row: 2, section: 0)], with: .automatic)
内容的提问来源于stack exchange,提问作者emelagumat
相关产品推荐
相关产品推荐

