iOS | 记tableSectionViewHeader奇怪的
问题描述
bug效果.gif在实现长按sectionHeader弹出菜单功能(使用UIMenuController)时,遇到了一个奇怪的bug。当选择菜单的选项对分组内item的操作时,即使分组内item全部移走了,即数据源少了一个分组,此时调用reloadData方法,界面显示出现了问题:
1、原来分组的sectionHeader不会消失,导致比预期多了一个分组;
2、使用UITableViewStylePlain样式滑动tableView时,靠下分组的sectionHeader会从靠前分组的sectionHeader后面跟着滑动,而不会像正常交互那样悬停在顶部。图中Rty分组的sectionHeader在滑动中本应该在某一偏移量时悬停在顶部,留意效果图,应该不难发现问题。
问题解决过程
1、看到tableView显示的UI效果混乱,第一感觉就是是否在子线程修改了UI,通常在子线程修改UI会引起一些奇怪的问题。通过打断点,确定没有在子线程修改UI。
2、sectionHeader是继承UITableViewHeaderFooterView实现的,tableView的delegate方法中并没有sectionHeader点击的方法。sectionHeader的点击事件传递是通过Block实现,观察到sectionHeader不会消失,推测循环引用导致了sectionHeader不能释放,一直显示在界面上。重新检查代码后并没有循环引用。
3、接下来的尝试就有点乱试的感觉了。
- 平时使用UITableView进行分组展示没有问题,这次使用的是UITableViewController,猜测是UITableViewController导致的问题,于是修改了类的继承关系,自己创建了一个tableView,同样有问题。
- 注释掉网络请求部分,用定时修改数据源,同样有问题。
- 。。。
4、多次尝试后,开始在stackOverflow等网站上查资料。查到的关于sectionHeader的问题无外乎以下情况:
- UITableViewStyleGrouped样式下,第一组sectionHeader不显示
- sectionHeader显示到了cell上,引起重叠
这些问题出现的原因基本上都和tableView的属性sectionHeaderHeight(即便所有分组高度一样,使用这个属性在某些情况也会出现问题,如导致在UITableViewStyleGrouped样式下第一个sectionHeader不显示)或者cell的高度计算有关。这些资料很容易查到,这里不再具体介绍解决办法。
5、以上这些问题表面上和我要解决的问题有些相似,实际上很不相同。查了国内外很多资料,依然为找到解决方案。接下来,只能静下心去仔细分析了(还是要靠自己~)。
6、问题出现在点击菜单选项之后,推测可能是点击菜单选项后的操作引起的问题,于是注释掉菜单选项的逻辑处理,替换成删除一个分组后刷新tableView的逻辑,问题还是存在。进一步,往上追踪,采用同样的方式,发现替换长按手势的处理逻辑后,问题竟然消失了。于是,问题的范围越来越小。然后采用二分的思想,不断追踪,最后确定到了这句代码上。
[sectionHeader becomeFirstResponder];
这句代码引起了tableView显示混乱,解决办法是通过一个变量引用一下当前长按的sectionHeader,在选择菜单选项后的逻辑中添加辞去响应者的操作。
[self.sectionHeader resignFirstResponder];
注:需要使sectionHeader成为第一响应者,UIMenuController才能弹出菜单。
讨论
同样的实现方式下,在cell中长按菜单模拟同样的逻辑不会有这个问题。也查阅了长按复制功能的实现,过程中同样没主动辞去响应者。关于tableView为什么在sectionHeader成为(becomeFirstResponder)后显示混乱,目前还没找到相关资料。如果您要什么见解,欢迎告知!