UITableView自定义Section Header点击后消失问题求助
问题分析与解决方案
我一眼就发现了导致Section Header点击后消失的核心问题:你错误地用UITableViewCell来实现Section Header,并且使用了cell的复用方法来获取它。UITableView的Cell复用池和Header/Footer View的复用池是完全分开的,当你把Cell当作Header返回时,TableView并不会把它识别为Header View来管理——当你执行插入/删除行的更新操作时,TableView会错误地回收这个"伪装"成Header的Cell,导致它从界面上消失。
具体修复步骤
1. 把自定义Header改成UITableViewHeaderFooterView子类
首先,将你的AccordianHeaderPrototypeCell改为继承自UITableViewHeaderFooterView,而不是UITableViewCell:
class AccordianHeaderView: UITableViewHeaderFooterView { @IBOutlet weak var headingLabel: UILabel! @IBOutlet weak var arrowImage: UIImageView! // 保留你原来的配置逻辑即可 }
2. 在ViewDidLoad中注册HeaderFooterView
替换原来注册Cell的代码,改为注册HeaderFooterView:
override func viewDidLoad() { super.viewDidLoad() // 移除原来的Cell注册代码 // tableView.register(UINib(nibName: "AccordianHeaderPrototypeCell", bundle: nil), forCellReuseIdentifier: "AccordianHeaderPrototypeCell") // 注册自定义HeaderFooterView itemsTableView.register(UINib(nibName: "AccordianHeaderView", bundle: nil), forHeaderFooterViewReuseIdentifier: "AccordianHeaderView") }
3. 修改viewForHeaderInSection方法
使用HeaderFooterView的复用方法来获取实例,而不是Cell的复用方法:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "AccordianHeaderView") as! AccordianHeaderView let cellinfo = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section] headerView.headingLabel.text = cellinfo.title headerView.arrowImage.tag = kHeaderSectionTag + section headerView.arrowImage.image = Constants.DOWNARROW_IMAGE headerView.tag = section // 复用前移除旧手势,避免重复添加导致的异常 headerView.gestureRecognizers?.forEach(headerView.removeGestureRecognizer) let headerTapGesture = UITapGestureRecognizer(target: self, action: #selector(self.sectionHeaderWasTouched(_:))) headerView.addGestureRecognizer(headerTapGesture) return headerView }
4. 更新手势响应方法的类型转换
因为现在sender.view是AccordianHeaderView,所以修改sectionHeaderWasTouched里的类型转换:
@objc func sectionHeaderWasTouched(_ sender: UITapGestureRecognizer) { guard let headerView = sender.view as? AccordianHeaderView else { return } let section = headerView.tag let eImageView = headerView.viewWithTag(kHeaderSectionTag + section) as? UIImageView // 保留你原来的展开/折叠逻辑不变 if self.expandedSectionHeaderNumber == -1 { self.expandedSectionHeaderNumber = section tableViewExpandSection(section, imageView: eImageView!) } else { if self.expandedSectionHeaderNumber == section { tableViewCollapeSection(section, imageView: eImageView!) } else { let cImageView = self.view.viewWithTag(kHeaderSectionTag + self.expandedSectionHeaderNumber) as? UIImageView tableViewCollapeSection(self.expandedSectionHeaderNumber, imageView: cImageView!) tableViewExpandSection(section, imageView: eImageView!) } } }
额外注意点
- 记得在Storyboard/XIB里把你的Header视图的类从
UITableViewCell改为AccordianHeaderView,并调整复用标识符为AccordianHeaderView。 - 复用HeaderFooterView时,一定要清理旧的手势或者状态,避免复用导致的异常(比如上面代码里移除已有手势的操作)。
这样修改后,TableView会正确识别你的自定义视图为Section Header,在执行更新操作时也不会错误地回收它,Header点击后消失的问题就解决了~
内容的提问来源于stack exchange,提问作者Rachna
相关产品推荐
相关产品推荐

