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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:17:37