场景
在开发中遇到了一个点击 TableViewCell 自定义模态出另一个控制器的坑:
- 尝试普通模态一个控制器,偶尔会有延迟显示。
- 自定义模态动画,必定会延迟显示,或者根本就不显示,必须二次点击视图才会显示出来。
解决
一开始以为是自定义模态动画出了问题,打断点发现都是即时执行的,流程也没有问题,就是会延迟 N 秒以上才模态出目标控制器。
然后用 Time Profiler 跑了一下,发现有以下两种情况:
- 延迟执行的时候,RunLoop 会延迟唤醒
- 压根不显示的情况,UIEventFetcher 压根就没有显示,Runloop 没有被唤醒
那既然是 RunLoop 没有被唤醒,那就好解决了,尝试在模态代码前面手动唤醒 RunLoop:
1 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { |
问题解决。
然后谷歌了一下为什么 didSelectRow 时存在 runloop 没有唤醒的情况,发现 Stack Overflow,还有一些别的论坛也有遇到这种坑的人,看了下,基本结论就是苹果的 didSelectRow 方法的 bug,其他开发者给出的解决方案是:
- 包一层主线程异步:
1 | dispatch_queue_t mainQueue = dispatch_get_main_queue(); |
- 不唤醒的情况只有在 TableViewCell 的 selectionStyle 为 none 的时候才发生, 这种情况修改 selectionStyle 也可以解决。
以上就是三个这种 bug 的解决方案。