问题描述
前几天在适配Xcode12 + iOS14发现了这样一个bug,因为在cell上添加视图的时候手抖没有把Button添加到TableViewCell的contentView上,而是直接添加到TableViewCell上
,导致Button的点击事件全都无法响应。
后来查看层级发现怎么contentView跑到了视图最上层??
探究过程
第一直觉是XCode12 + iOS14上苹果改了底层实现把ContentView放到了最上层,就出现了这的问题(其实并不是这样的,后面会讲原因)。
最近正好没那么忙打算具体探究一下问题的原因:
通过添加 -[UIView addSubview:]
的Symbolic BreakPoint
的断点,来获取TableViewCell 添加 contentView的具体时机和调用堆栈。
ContentView 添加到Cell上的时机:
在iOS14以前:
contentView是在[UITableViewCell initWithStyle:resueIdentifier]
的初始化时第一个添加到View上。所以在最底层。
在iOS14上:
contentView 使用的是懒加载的方式生成。 在 cell即将要显示,调用
-[UITableView _configureCellForDisplay:forIndexPath:]_block_invoke
的时候需要调整ContentView的布局,懒加载生成ContentView 并加载到Cell上。 所以就有了ContentView在最上层的bug了。
再通过对比iOS13和iOS14的Cell的初始化方法[UITableViewCell initWithStyle:reuseIdentifier:]
断点调试。
发现 iOS14上Cell的init方法多出了_UITableViewCellEnableLazyContentView
的方法,可以完全不用懂汇编,通过方法名就可以知道在iOS14上ContentView使用的是懒加载生成的。
_UITableViewCellEnableLazyContentView
是一个默认返回true的方法,返回值为true的话在Cell的初始化方法中默认不初始化ContentView。 而是在调用的时候才创建ContentView并添加到Cell上
。
Test一下:
这里写一个最简单的cell,只添加一个红色的按钮。
只是在addSubView(redButton)
之前随便调用一下contentView的lazy方法,这里就设置个绿色的背景色。
这个时候绿色的contentView就又回到了redButton后面😅😅。。正常了。。
感兴趣的同学可以写个Demo感受一下。
感悟:
这个妥妥是苹果的bug。
可能是疫情的时候哪个阿三在家状态不好没有考虑完全写出了这样的逻辑。
在Xcode12.2和iOS14正式版本这个bug还没有修。。
可能是不打算修了。。
最近作为苹果开发者,幸福感急剧下降啊。。