Swift中UIPickerView为何多次调用numberOfComponents等代理方法
UIPickerView数据源代理方法多次调用的原因
这是UIPickerView的正常运行逻辑,并非代码bug,系统会在不同生命周期节点主动调用数据源方法拉取信息,具体触发场景和你给出的日志对应关系如下:
- 首次挂载布局阶段:当你把UIPickerView添加到视图层级、完成初始约束/frame设置时,系统会至少两次调用
numberOfComponents:第一次是picker加入视图树时确认基础组件结构,第二次是完成布局计算后校验结构合法性。之后会连续调用numberOfRowsInComponent,用来计算滚轮的总可滚动高度、每一行的初始位置,这就是日志里刚进入open_plot_picker()就连续打印2次列数、6次行数的原因。 - 初始渲染阶段:UIPickerView不会一次性请求所有行的展示内容,只会优先请求当前可视区域内的行标题,日志里最开始只拿到row0、row1的
titleForRow回调,就是因为初始状态下picker可视区域只露出前两行,可视区外的行不会触发内容请求。 - 状态变更触发重载:当代码里调用了
reloadAllComponents()、reloadComponent:、selectRow:inComponent:animated:,或者修改了picker的frame、约束、显隐属性时,系统会重新触发一轮列数、行数拉取,重新计算布局。日志里open_plot_picker()执行完成、select_plots_UIButton()回调结束后又出现一轮列数、行数请求,就是这类操作触发的。 - 滚动交互阶段:用户滑动picker的过程中,系统会持续调用
numberOfRowsInComponent做滚动边界校验,避免滚动位置超出总行数范围,同时按需请求刚进入可视区域的行标题。日志里后续逐行拿到row2到row5的标题回调,就是滚动过程中各行进入可视区触发的,中间穿插的行数调用都是边界校验的正常逻辑。
注意:不要在numberOfComponents、numberOfRowsInComponent方法里写任何耗时逻辑,这两个方法会被系统高频调用,一旦包含耗时操作会直接导致picker滑动卡顿、掉帧。如果列数、行数是固定值直接返回常量即可,不要在这两个方法里做计算、IO、网络请求类操作。
内容的提问来源于stack exchange,提问作者Doug Null
相关产品推荐
相关产品推荐

