滚动视图的ReloadData和VisibleCells

iOS基础

作为UIScrollView的子类UITableViewUICollectionView是我们平时开发中最常使用的两个列表控件。同时在一些复杂的页面中也经常嵌套使用,同时由于对其有些方法理解的不够深入,很容易导致一些比较诡异的问题。

因此这里单独写一篇文章来介绍这两个常用控件中的几个常用的方法,希望可以加深大家对UITableViewUICollectionView的理解。

数据刷新 reloadData

为了更好的理解方法的调用链,我们会添加一个队runloop的监听

UITableView

demo

上图是我们demo的样子(只有一个cell)。

下面我们来看代码:

1
2
3
4
5
6
7
- (void)reloadTableData {

[self.tableView reloadData];

NSLog(@"reloadData 执行完成");

}

点击Demo中左上角的reloadData会调用reloadTableData方法。

下面我们来看控制台打印结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2019-10-08 19:32:21.875441+0800 LayoutIfNeed[3662:223502] RunLoop被唤醒

2019-10-08 19:32:21.876164+0800 LayoutIfNeed[3662:223502] RunLoop即将处理Timer事件

2019-10-08 19:32:21.876295+0800 LayoutIfNeed[3662:223502] RunLoop即将处理Source事件

2019-10-08 19:32:21.877622+0800 LayoutIfNeed[3662:223502] -[ULTableView reloadData]

2019-10-08 19:32:21.880310+0800 LayoutIfNeed[3662:223502] -[ViewController numberOfSectionsInTableView:]

2019-10-08 19:32:21.880779+0800 LayoutIfNeed[3662:223502] -[ULTableView setNeedsLayout]

2019-10-08 19:32:21.881075+0800 LayoutIfNeed[3662:223502] -[ViewController tableView:numberOfRowsInSection:]

2019-10-08 19:32:21.881755+0800 LayoutIfNeed[3662:223502] -[ULTableView setNeedsLayout]

2019-10-08 19:32:21.881921+0800 LayoutIfNeed[3662:223502] -[ULTableView setNeedsLayout]

2019-10-08 19:32:21.882095+0800 LayoutIfNeed[3662:223502] -[ULTableView setNeedsLayout]

2019-10-08 19:32:21.882227+0800 LayoutIfNeed[3662:223502] reloadData 执行完成

2019-10-08 19:32:21.883112+0800 LayoutIfNeed[3662:223502] RunLoop即将处理Timer事件

2019-10-08 19:32:21.883582+0800 LayoutIfNeed[3662:223502] RunLoop即将处理Source事件

2019-10-08 19:32:21.906191+0800 LayoutIfNeed[3662:223502] RunLoop即将休眠

2019-10-08 19:32:21.907129+0800 LayoutIfNeed[3662:223502] -[ULTableView layoutSubviews]

2019-10-08 19:32:21.907349+0800 LayoutIfNeed[3662:223502] -[ULTableView dequeueReusableCellWithIdentifier:]

2019-10-08 19:32:21.908622+0800 LayoutIfNeed[3662:223502] -[ViewController tableView:cellForRowAtIndexPath:] 0 0

2019-10-08 19:32:21.909076+0800 LayoutIfNeed[3662:223502] -[ViewController tableView:heightForRowAtIndexPath:]

2019-10-08 19:32:21.909236+0800 LayoutIfNeed[3662:223502] -[ULTableView setNeedsLayout]

2019-10-08 19:32:21.909670+0800 LayoutIfNeed[3662:223502] -[ULTableView setNeedsLayout]

2019-10-08 19:32:21.909991+0800 LayoutIfNeed[3662:223502] -[ULTableView layoutSubviews]

首先看到了我们比较熟悉的方法numberOfSectionsInTableViewdequeueReusableCellWithIdentifiertableView:heightForRowAtIndexPath:tableView:cellForRowAtIndexPath:

这些方法都是我们比较熟悉的方法了,这里我就不再赘述。

其次根据log我们可以比较清晰的的出另外一个结论:
reloadData是一个异步方法,reloadData在当前的Runloop中只是做了setNeedsLayout(表示当前view在下一个runloop到来时需要被更新),显然当前Runloop结束后才根据之前设置setNeedsLayout的标记执行layoutSubviews方法进而触发页面的更新

UICollectionView

demo

上图是我们demo的样子(只展示了一个cell)。

下面我们在来看下代码:

1
2
3
4
- (void)reloadCollectionViewData {
[self.collectionView reloadData];
NSLog(@"reloadData 执行完成");
}

点击demo的左上角按钮即调用reloadData方法
下面看下打印结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2019-10-19 21:50:36.219755+0800 LayoutIfNeed[4002:2375227] RunLoop被唤醒
2019-10-19 21:50:36.220045+0800 LayoutIfNeed[4002:2375227] RunLoop即将处理Timer事件
2019-10-19 21:50:36.220326+0800 LayoutIfNeed[4002:2375227] RunLoop即将处理Source事件
2019-10-19 21:50:36.221302+0800 LayoutIfNeed[4002:2375227] -[ULCollectionView reloadData]
2019-10-19 21:50:36.221610+0800 LayoutIfNeed[4002:2375227] -[ULCollectionView setNeedsLayout]
2019-10-19 21:50:36.221826+0800 LayoutIfNeed[4002:2375227] -[ULCollectionView setNeedsLayout]
2019-10-19 21:50:36.221993+0800 LayoutIfNeed[4002:2375227] -[ULCollectionView setNeedsLayout]
2019-10-19 21:50:36.222109+0800 LayoutIfNeed[4002:2375227] -[ULCollectionView setNeedsLayout]
2019-10-19 21:50:36.222532+0800 LayoutIfNeed[4002:2375227] -[ULCollectionView setNeedsLayout]
2019-10-19 21:50:36.222939+0800 LayoutIfNeed[4002:2375227] reloadData 执行完成
2019-10-19 21:50:36.223924+0800 LayoutIfNeed[4002:2375227] RunLoop即将处理Timer事件
2019-10-19 21:50:36.224480+0800 LayoutIfNeed[4002:2375227] RunLoop即将处理Source事件
2019-10-19 21:50:36.225190+0800 LayoutIfNeed[4002:2375227] RunLoop即将休眠
2019-10-19 21:50:36.226107+0800 LayoutIfNeed[4002:2375227] -[ULCollectionView layoutSubviews]
2019-10-19 21:50:36.226609+0800 LayoutIfNeed[4002:2375227] -[ULCollectionViewController numberOfSectionsInCollectionView:]
2019-10-19 21:50:36.226864+0800 LayoutIfNeed[4002:2375227] -[ULCollectionViewController collectionView:numberOfItemsInSection:]
2019-10-19 21:50:36.323486+0800 LayoutIfNeed[4002:2375227] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-19 21:50:36.324053+0800 LayoutIfNeed[4002:2375227] -[ULCollectionViewController collectionView:cellForItemAtIndexPath:]

从log中我们看出UICollectionViewUITableView的效果一致。因此其结论与UITableView也是一致。

tableView中嵌套collectionView

demo

demo中tableView含两个cell 第一个cell上add一个collectionView,第二个cell为一个tableViewCell

点击右上角reloadTableData:

1
2
3
4
- (void)reloadTableData {
NSLog(@"%s",__func__);
[self.tableView reloadData];
}

log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2019-10-20 08:45:10.415969+0800 LayoutIfNeed[5741:2466905] UIInnerCollectionView RunLoop即将处理Source事件
2019-10-20 08:45:10.417080+0800 LayoutIfNeed[5741:2466905] -[TableCollectionViewController reloadTableData]
2019-10-20 08:45:10.417207+0800 LayoutIfNeed[5741:2466905] -[ULTableView reloadData]
2019-10-20 08:45:10.417477+0800 LayoutIfNeed[5741:2466905] -[TableCollectionViewController numberOfSectionsInTableView:]
2019-10-20 08:45:10.417632+0800 LayoutIfNeed[5741:2466905] -[ULTableView setNeedsLayout]
2019-10-20 08:45:10.418072+0800 LayoutIfNeed[5741:2466905] -[TableCollectionViewController tableView:numberOfRowsInSection:]
2019-10-20 08:45:10.418353+0800 LayoutIfNeed[5741:2466905] -[ULTableView setNeedsLayout]
2019-10-20 08:45:10.418493+0800 LayoutIfNeed[5741:2466905] -[ULTableView setNeedsLayout]
2019-10-20 08:45:10.418716+0800 LayoutIfNeed[5741:2466905] -[ULTableView setNeedsLayout]
2019-10-20 08:45:10.419573+0800 LayoutIfNeed[5741:2466905] TableCollectionViewController RunLoop即将处理Timer事件
2019-10-20 08:45:10.419701+0800 LayoutIfNeed[5741:2466905] UIInnerCollectionView RunLoop即将处理Timer事件
2019-10-20 08:45:10.419813+0800 LayoutIfNeed[5741:2466905] TableCollectionViewController RunLoop即将处理Source事件
2019-10-20 08:45:10.420023+0800 LayoutIfNeed[5741:2466905] UIInnerCollectionView RunLoop即将处理Source事件
2019-10-20 08:45:10.420644+0800 LayoutIfNeed[5741:2466905] TableCollectionViewController RunLoop即将休眠
2019-10-20 08:45:10.420774+0800 LayoutIfNeed[5741:2466905] UIInnerCollectionView RunLoop即将休眠
2019-10-20 08:45:10.421129+0800 LayoutIfNeed[5741:2466905] -[ULTableView layoutSubviews]
2019-10-20 08:45:10.421393+0800 LayoutIfNeed[5741:2466905] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 08:45:10.421851+0800 LayoutIfNeed[5741:2466905] -[TableCollectionViewController tableView:cellForRowAtIndexPath:] 0 0
2019-10-20 08:45:10.422269+0800 LayoutIfNeed[5741:2466905] -[ULCollectionView reloadData]
2019-10-20 08:45:10.422648+0800 LayoutIfNeed[5741:2466905] -[ULCollectionView setNeedsLayout]
2019-10-20 08:45:10.423020+0800 LayoutIfNeed[5741:2466905] -[ULCollectionView setNeedsLayout]
2019-10-20 08:45:10.423360+0800 LayoutIfNeed[5741:2466905] -[ULCollectionView setNeedsLayout]
2019-10-20 08:45:10.423758+0800 LayoutIfNeed[5741:2466905] -[ULCollectionView setNeedsLayout]
2019-10-20 08:45:10.424125+0800 LayoutIfNeed[5741:2466905] -[ULCollectionView setNeedsLayout]
2019-10-20 08:45:10.424765+0800 LayoutIfNeed[5741:2466905] -[TableCollectionViewController tableView:heightForRowAtIndexPath:]
2019-10-20 08:45:10.424898+0800 LayoutIfNeed[5741:2466905] -[ULTableView setNeedsLayout]
2019-10-20 08:45:10.425206+0800 LayoutIfNeed[5741:2466905] -[ULCollectionView layoutSubviews]
2019-10-20 08:45:10.425470+0800 LayoutIfNeed[5741:2466905] -[UIInnerCollectionView numberOfSectionsInCollectionView:]
2019-10-20 08:45:10.425776+0800 LayoutIfNeed[5741:2466905] -[UIInnerCollectionView collectionView:numberOfItemsInSection:]
2019-10-20 08:45:10.427618+0800 LayoutIfNeed[5741:2466905] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-20 08:45:10.427884+0800 LayoutIfNeed[5741:2466905] -[UIInnerCollectionView collectionView:cellForItemAtIndexPath:]
2019-10-20 08:45:10.428257+0800 LayoutIfNeed[5741:2466905] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 08:45:10.428505+0800 LayoutIfNeed[5741:2466905] -[TableCollectionViewController tableView:cellForRowAtIndexPath:] 0 1
2019-10-20 08:45:10.429038+0800 LayoutIfNeed[5741:2466905] -[TableCollectionViewController tableView:heightForRowAtIndexPath:]
2019-10-20 08:45:10.429178+0800 LayoutIfNeed[5741:2466905] -[ULTableView setNeedsLayout]
2019-10-20 08:45:10.429590+0800 LayoutIfNeed[5741:2466905] -[ULTableView setNeedsLayout]
2019-10-20 08:45:10.429988+0800 LayoutIfNeed[5741:2466905] -[ULTableView layoutSubviews]

根据上面的log我们看到UITableView在执行reloadData之后仍让只是做了标记。在下一个runloop到来之后触发UITableViewlayoutSubviews方法进而又触发该Cell中UICollectionView的reloadData操作

如果我们不主动的调用reloadData呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2019-10-20 09:05:20.372536+0800 LayoutIfNeed[5867:2475442] -[TableCollectionViewController reloadTableData]
2019-10-20 09:05:40.060940+0800 LayoutIfNeed[5867:2475442] -[ULTableView reloadData]
2019-10-20 09:05:40.061223+0800 LayoutIfNeed[5867:2475442] -[TableCollectionViewController numberOfSectionsInTableView:]
2019-10-20 09:05:40.061361+0800 LayoutIfNeed[5867:2475442] -[ULTableView setNeedsLayout]
2019-10-20 09:05:40.061539+0800 LayoutIfNeed[5867:2475442] -[TableCollectionViewController tableView:numberOfRowsInSection:]
2019-10-20 09:05:40.061691+0800 LayoutIfNeed[5867:2475442] -[ULTableView setNeedsLayout]
2019-10-20 09:05:40.061812+0800 LayoutIfNeed[5867:2475442] -[ULTableView setNeedsLayout]
2019-10-20 09:05:40.061950+0800 LayoutIfNeed[5867:2475442] -[ULTableView setNeedsLayout]
2019-10-20 09:05:40.062454+0800 LayoutIfNeed[5867:2475442] -[ULTableView layoutSubviews]
2019-10-20 09:05:40.062653+0800 LayoutIfNeed[5867:2475442] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 09:05:40.062829+0800 LayoutIfNeed[5867:2475442] -[TableCollectionViewController tableView:cellForRowAtIndexPath:] 0 0
2019-10-20 09:06:08.551189+0800 LayoutIfNeed[5867:2475442] -[TableCollectionViewController tableView:heightForRowAtIndexPath:]
2019-10-20 09:06:08.551448+0800 LayoutIfNeed[5867:2475442] -[ULTableView setNeedsLayout]
2019-10-20 09:06:08.551836+0800 LayoutIfNeed[5867:2475442] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 09:06:08.552087+0800 LayoutIfNeed[5867:2475442] -[TableCollectionViewController tableView:cellForRowAtIndexPath:] 0 1
2019-10-20 09:06:08.552490+0800 LayoutIfNeed[5867:2475442] -[TableCollectionViewController tableView:heightForRowAtIndexPath:]
2019-10-20 09:06:08.552625+0800 LayoutIfNeed[5867:2475442] -[ULTableView setNeedsLayout]
2019-10-20 09:06:08.552972+0800 LayoutIfNeed[5867:2475442] -[ULTableView setNeedsLayout]
2019-10-20 09:06:08.553263+0800 LayoutIfNeed[5867:2475442] -[ULTableView layoutSubviews]

根据上面的日志我们看到,外部TableView的reloadData甚至是TableView的layoutSubviews操作均不会影响Cell中CollectionView。

CollectionView中嵌套tableView

demo

点击右上角reloadData 执行下面的代码

1
2
3
4
- (void)reloadCollectionViewData {
[self.collectionView reloadData];
NSLog(@"reloadData 执行完成");
}

下面我们来看下log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2019-10-20 08:48:14.430891+0800 LayoutIfNeed[5782:2468993] -[ULCollectionView reloadData]
2019-10-20 08:48:14.431133+0800 LayoutIfNeed[5782:2468993] -[ULCollectionView setNeedsLayout]
2019-10-20 08:48:14.431393+0800 LayoutIfNeed[5782:2468993] -[ULCollectionView setNeedsLayout]
2019-10-20 08:48:14.431817+0800 LayoutIfNeed[5782:2468993] -[ULCollectionView setNeedsLayout]
2019-10-20 08:48:14.432207+0800 LayoutIfNeed[5782:2468993] -[ULCollectionView setNeedsLayout]
2019-10-20 08:48:14.432420+0800 LayoutIfNeed[5782:2468993] -[ULCollectionView setNeedsLayout]
2019-10-20 08:48:14.432648+0800 LayoutIfNeed[5782:2468993] reloadData 执行完成
2019-10-20 08:48:14.433422+0800 LayoutIfNeed[5782:2468993] CollectionTableViewController RunLoop即将处理Timer事件
2019-10-20 08:48:14.433560+0800 LayoutIfNeed[5782:2468993] UIInnerTableView RunLoop即将处理Timer事件
2019-10-20 08:48:14.433762+0800 LayoutIfNeed[5782:2468993] CollectionTableViewController RunLoop即将处理Source事件
2019-10-20 08:48:14.434047+0800 LayoutIfNeed[5782:2468993] UIInnerTableView RunLoop即将处理Source事件
2019-10-20 08:48:14.434736+0800 LayoutIfNeed[5782:2468993] CollectionTableViewController RunLoop即将休眠
2019-10-20 08:48:14.434865+0800 LayoutIfNeed[5782:2468993] UIInnerTableView RunLoop即将休眠
2019-10-20 08:48:14.435240+0800 LayoutIfNeed[5782:2468993] -[ULCollectionView layoutSubviews]
2019-10-20 08:48:14.435422+0800 LayoutIfNeed[5782:2468993] -[CollectionTableViewController numberOfSectionsInCollectionView:]
2019-10-20 08:48:14.435568+0800 LayoutIfNeed[5782:2468993] -[CollectionTableViewController collectionView:numberOfItemsInSection:]
2019-10-20 08:48:14.437589+0800 LayoutIfNeed[5782:2468993] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-20 08:48:14.438094+0800 LayoutIfNeed[5782:2468993] -[CollectionTableViewController collectionView:cellForItemAtIndexPath:]
2019-10-20 08:48:14.438444+0800 LayoutIfNeed[5782:2468993] -[ULTableView reloadData]
2019-10-20 08:48:14.438847+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView numberOfSectionsInTableView:]
2019-10-20 08:48:14.439129+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.439520+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:numberOfRowsInSection:]
2019-10-20 08:48:14.439828+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.440130+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.440494+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.441025+0800 LayoutIfNeed[5782:2468993] -[ULTableView layoutSubviews]
2019-10-20 08:48:14.441239+0800 LayoutIfNeed[5782:2468993] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 08:48:14.441523+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 0
2019-10-20 08:48:14.442092+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 08:48:14.442281+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.442722+0800 LayoutIfNeed[5782:2468993] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 08:48:14.443052+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 1
2019-10-20 08:48:14.443557+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 08:48:14.443796+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.444251+0800 LayoutIfNeed[5782:2468993] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 08:48:14.444577+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 2
2019-10-20 08:48:14.445056+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 08:48:14.445428+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.445989+0800 LayoutIfNeed[5782:2468993] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 08:48:14.446264+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 3
2019-10-20 08:48:14.446693+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 08:48:14.447040+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.447631+0800 LayoutIfNeed[5782:2468993] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 08:48:14.448047+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 4
2019-10-20 08:48:14.448584+0800 LayoutIfNeed[5782:2468993] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 08:48:14.448971+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.449616+0800 LayoutIfNeed[5782:2468993] -[ULTableView setNeedsLayout]
2019-10-20 08:48:14.450075+0800 LayoutIfNeed[5782:2468993] -[ULTableView layoutSubviews]

上述结果同TableView中嵌套CollectionView相似。被嵌套的控件的

那么我们同样看下如果我们在TableView的CellForRow方法中不主动调用reloadData时log的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2019-10-20 08:58:07.783966+0800 LayoutIfNeed[5845:2473209] -[ULCollectionView reloadData]
2019-10-20 08:58:07.784219+0800 LayoutIfNeed[5845:2473209] -[ULCollectionView setNeedsLayout]
2019-10-20 08:58:07.784382+0800 LayoutIfNeed[5845:2473209] -[ULCollectionView setNeedsLayout]
2019-10-20 08:58:07.784507+0800 LayoutIfNeed[5845:2473209] -[ULCollectionView setNeedsLayout]
2019-10-20 08:58:07.784605+0800 LayoutIfNeed[5845:2473209] -[ULCollectionView setNeedsLayout]
2019-10-20 08:58:07.784705+0800 LayoutIfNeed[5845:2473209] -[ULCollectionView setNeedsLayout]
2019-10-20 08:58:07.784817+0800 LayoutIfNeed[5845:2473209] reloadData 执行完成
2019-10-20 08:58:07.785197+0800 LayoutIfNeed[5845:2473209] CollectionTableViewController RunLoop即将处理Timer事件
2019-10-20 08:58:07.785327+0800 LayoutIfNeed[5845:2473209] UIInnerTableView RunLoop即将处理Timer事件
2019-10-20 08:58:07.785671+0800 LayoutIfNeed[5845:2473209] CollectionTableViewController RunLoop即将处理Source事件
2019-10-20 08:58:07.786006+0800 LayoutIfNeed[5845:2473209] UIInnerTableView RunLoop即将处理Source事件
2019-10-20 08:58:07.786776+0800 LayoutIfNeed[5845:2473209] CollectionTableViewController RunLoop即将休眠
2019-10-20 08:58:07.786927+0800 LayoutIfNeed[5845:2473209] UIInnerTableView RunLoop即将休眠
2019-10-20 08:58:07.787353+0800 LayoutIfNeed[5845:2473209] -[ULCollectionView layoutSubviews]
2019-10-20 08:58:07.787514+0800 LayoutIfNeed[5845:2473209] -[CollectionTableViewController numberOfSectionsInCollectionView:]
2019-10-20 08:58:07.787615+0800 LayoutIfNeed[5845:2473209] -[CollectionTableViewController collectionView:numberOfItemsInSection:]
2019-10-20 08:58:07.789470+0800 LayoutIfNeed[5845:2473209] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-20 08:58:07.789994+0800 LayoutIfNeed[5845:2473209] -[CollectionTableViewController collectionView:cellForItemAtIndexPath:]

根据上面的log我们可以得出一个结论 如果不主动触发,外部的CollectionView调用reloadData并不会影响cell中嵌套的TableView

VisibleCell

UITableView

demo同上

下面我们直接看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (void)reloadTableData {

[self.tableView reloadData];

NSLog(@"reloadData 执行完成");

NSArray *array = [self.tableView visibleCells];

NSLog(@"visibleCells----:%@",@(array.count));


dispatch_async(dispatch_get_main_queue(), ^{

NSArray *array = [self.tableView visibleCells];

NSLog(@"visibleCells==== :%@",@(array.count));
});

}

由于在reloadData中我们知道该方法是一个异步的,一次在获取visibleCell的时候我们使用两种方法

  • 1、直接调用[self.tableView visibleCells]
  • 2、使用GCD在下一个runloop到来时在去获取Runloop

下面看下上面代码的执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2019-10-08 19:40:28.825840+0800 LayoutIfNeed[3696:229565] RunLoop被唤醒

2019-10-08 19:40:28.826209+0800 LayoutIfNeed[3696:229565] RunLoop即将处理Timer事件

2019-10-08 19:40:28.826463+0800 LayoutIfNeed[3696:229565] RunLoop即将处理Source事件

2019-10-08 19:40:28.827665+0800 LayoutIfNeed[3696:229565] -[ULTableView reloadData]

2019-10-08 19:40:28.828167+0800 LayoutIfNeed[3696:229565] -[ViewController numberOfSectionsInTableView:]

2019-10-08 19:40:28.830161+0800 LayoutIfNeed[3696:229565] -[ULTableView setNeedsLayout]

2019-10-08 19:40:28.830560+0800 LayoutIfNeed[3696:229565] -[ViewController tableView:numberOfRowsInSection:]

2019-10-08 19:40:28.830946+0800 LayoutIfNeed[3696:229565] -[ULTableView setNeedsLayout]

2019-10-08 19:40:28.831849+0800 LayoutIfNeed[3696:229565] -[ULTableView setNeedsLayout]

2019-10-08 19:40:28.832015+0800 LayoutIfNeed[3696:229565] -[ULTableView setNeedsLayout]

2019-10-08 19:40:28.832149+0800 LayoutIfNeed[3696:229565] reloadData 执行完成

2019-10-08 19:40:28.832346+0800 LayoutIfNeed[3696:229565] -[ULTableView dequeueReusableCellWithIdentifier:]

2019-10-08 19:40:28.832904+0800 LayoutIfNeed[3696:229565] -[ViewController tableView:cellForRowAtIndexPath:] 0 0

2019-10-08 19:40:28.833739+0800 LayoutIfNeed[3696:229565] -[ViewController tableView:heightForRowAtIndexPath:]

2019-10-08 19:40:28.833904+0800 LayoutIfNeed[3696:229565] -[ULTableView setNeedsLayout]

2019-10-08 19:40:28.834391+0800 LayoutIfNeed[3696:229565] -[ULTableView setNeedsLayout]

2019-10-08 19:40:28.834894+0800 LayoutIfNeed[3696:229565] visibleCells----:1

2019-10-08 19:40:28.835912+0800 LayoutIfNeed[3696:229565] visibleCells==== :1

2019-10-08 19:40:28.836664+0800 LayoutIfNeed[3696:229565] RunLoop即将处理Timer事件

2019-10-08 19:40:28.837310+0800 LayoutIfNeed[3696:229565] RunLoop即将处理Source事件

2019-10-08 19:40:28.838118+0800 LayoutIfNeed[3696:229565] RunLoop即将休眠

2019-10-08 19:40:28.839862+0800 LayoutIfNeed[3696:229565] -[ULTableView layoutSubviews]

通过log我们可以看到

1
两次`visibleCells`方法都返回了正确的cells数据是一致的且均是正确的

疑问一:

reloadData是异步的,它是会调用setNeedLayout方法标记当前view在下一次Runloop到来时刷新页面,为什么获取visibleCell会是正确的?

疑问二:

为什么cellforRow的方法调用不是在reloadData的下一次Runloop到来时才被调用而是在当前的Runloop中就被调用?

下面我们通过在cellForRow方法中添加断点的方式确认下在visibleCell被调用的时候都做了什么。

调用堆栈

根据这个断点的截图我们发现在调用visibleCell(截图右侧)的时候会触发createPreparedCell的调用,这个方法又间接的调用了cellForRow的代理方法。因此我们在当前runloop中使用visibleCell就可以获取到正确的值。

UICollectionView

Demo同上

下面我们来直接看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (void)reloadCollectionViewData {

[self.collectionView reloadData];

NSLog(@"reloadData 执行完成");


NSArray *array = [self.collectionView visibleCells];

NSLog(@"visibleCells----:%@",@(array.count));


dispatch_async(dispatch_get_main_queue(), ^{

NSArray *array = [self.collectionView visibleCells];

NSLog(@"visibleCells==== :%@",@(array.count));

});

}

—————–我是分割线——————

大家可以思考下结果,然后在接着往下看…..

—————–我是分割线——————

下面我们直接看下log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2019-10-09 15:09:32.564096+0800 LayoutIfNeed[5995:609901] RunLoop被唤醒
2019-10-09 15:09:32.564291+0800 LayoutIfNeed[5995:609901] RunLoop即将处理Timer事件
2019-10-09 15:09:32.564403+0800 LayoutIfNeed[5995:609901] RunLoop即将处理Source事件
2019-10-09 15:09:32.565137+0800 LayoutIfNeed[5995:609901] -[ULCollectionView reloadData]
2019-10-09 15:09:32.565606+0800 LayoutIfNeed[5995:609901] -[ULCollectionView setNeedsLayout]
2019-10-09 15:09:32.565806+0800 LayoutIfNeed[5995:609901] -[ULCollectionView setNeedsLayout]
2019-10-09 15:09:32.566099+0800 LayoutIfNeed[5995:609901] -[ULCollectionView setNeedsLayout]
2019-10-09 15:09:32.566650+0800 LayoutIfNeed[5995:609901] -[ULCollectionView setNeedsLayout]
2019-10-09 15:09:32.567124+0800 LayoutIfNeed[5995:609901] -[ULCollectionView setNeedsLayout]
2019-10-09 15:09:32.567806+0800 LayoutIfNeed[5995:609901] reloadData 执行完成
2019-10-09 15:09:32.568103+0800 LayoutIfNeed[5995:609901] visibleCells----:0
2019-10-09 15:09:32.569715+0800 LayoutIfNeed[5995:609901] visibleCells==== :0
2019-10-09 15:09:32.570232+0800 LayoutIfNeed[5995:609901] RunLoop即将处理Timer事件
2019-10-09 15:09:32.570603+0800 LayoutIfNeed[5995:609901] RunLoop即将处理Source事件
2019-10-09 15:09:32.571044+0800 LayoutIfNeed[5995:609901] RunLoop即将处理Timer事件
2019-10-09 15:09:32.571513+0800 LayoutIfNeed[5995:609901] RunLoop即将处理Source事件
2019-10-09 15:09:32.572296+0800 LayoutIfNeed[5995:609901] RunLoop即将休眠
2019-10-09 15:09:32.572800+0800 LayoutIfNeed[5995:609901] -[ULCollectionView layoutSubviews]
2019-10-09 15:09:32.572981+0800 LayoutIfNeed[5995:609901] -[ULCollectionViewController numberOfSectionsInCollectionView:]
2019-10-09 15:09:32.573112+0800 LayoutIfNeed[5995:609901] -[ULCollectionViewController collectionView:numberOfItemsInSection:]
2019-10-09 15:09:32.575343+0800 LayoutIfNeed[5995:609901] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-09 15:09:32.575858+0800 LayoutIfNeed[5995:609901] -[ULCollectionViewController collectionView:cellForItemAtIndexPath:]
2019-10-09 15:09:32.576419+0800 LayoutIfNeed[5995:609901] -[ULCollectionView layoutSubviews] visibleCell 1

额!!!!!!!!!!!!!!!!

通过log我们发现:

我们两次获取visibleCell的数据均不正确,但是我们发现

1
2019-10-09 15:09:32.576419+0800 LayoutIfNeed[5995:609901] -[ULCollectionView layoutSubviews] visibleCell 1

在collectionView执行完layoutSubviews后获取的visibleCell是正确的。

同时我们注意到调用visibleCell时并没有像UITableView一样触发cellForRow被提前调用。

下面我们在观察下cellForRow被调用的时候的调用栈

调用栈

我们看到对于UICollectionView在调用了layoutSubviews之后才会触发下面方法的调用
-[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:]

这个位置是跟UITableView是一致的!

UITableView中嵌套UICollectionView

首先我们来确认下 如果在UITableView中调用了visibleCell是否会影响到内部的CollectionView

页面加载完成后

下面我们直接看log

1
2
2019-10-20 09:42:36.408243+0800 LayoutIfNeed[6044:2489041] -[TableCollectionViewController reloadTableData]
2019-10-20 09:42:36.408414+0800 LayoutIfNeed[6044:2489041] visibleCells----:2

log 显示页面加载完成后 我们在调用visibleCell时不会影响内部的CollectionView

页面加载完成前
1
2
3
[self.view addSubview:self.tableView];
NSArray *array = [self.tableView visibleCells];
NSLog(@"visibleCells----:%@",@(array.count));

这里为了验证效果 我们暂时不主动调用reloadData

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2019-10-20 09:48:53.813778+0800 LayoutIfNeed[6081:2491415] -[ULTableView setNeedsLayout]
2019-10-20 09:48:53.814644+0800 LayoutIfNeed[6081:2491415] visibleCells----:0
2019-10-20 09:48:53.816761+0800 LayoutIfNeed[6081:2491415] -[TableCollectionViewController numberOfSectionsInTableView:]
2019-10-20 09:48:53.816960+0800 LayoutIfNeed[6081:2491415] -[TableCollectionViewController tableView:numberOfRowsInSection:]
2019-10-20 09:48:53.817162+0800 LayoutIfNeed[6081:2491415] -[ULTableView setNeedsLayout]
2019-10-20 09:48:53.817733+0800 LayoutIfNeed[6081:2491415] -[ULTableView setNeedsLayout]
2019-10-20 09:48:53.828370+0800 LayoutIfNeed[6081:2491415] -[ULTableView layoutSubviews]
2019-10-20 09:48:53.828573+0800 LayoutIfNeed[6081:2491415] -[ULTableView reloadData]
2019-10-20 09:48:53.828713+0800 LayoutIfNeed[6081:2491415] -[TableCollectionViewController numberOfSectionsInTableView:]
2019-10-20 09:48:53.828853+0800 LayoutIfNeed[6081:2491415] -[TableCollectionViewController tableView:numberOfRowsInSection:]
2019-10-20 09:48:53.828974+0800 LayoutIfNeed[6081:2491415] -[ULTableView setNeedsLayout]
2019-10-20 09:48:53.829170+0800 LayoutIfNeed[6081:2491415] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 09:48:53.829604+0800 LayoutIfNeed[6081:2491415] -[TableCollectionViewController tableView:cellForRowAtIndexPath:] 0 0
2019-10-20 09:48:53.830285+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView setNeedsLayout]
2019-10-20 09:48:53.830449+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView setNeedsLayout]
2019-10-20 09:48:53.830576+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView setNeedsLayout]
2019-10-20 09:48:53.830811+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView reloadData]
2019-10-20 09:48:53.830948+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView setNeedsLayout]
2019-10-20 09:48:53.831085+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView setNeedsLayout]
2019-10-20 09:48:53.831213+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView setNeedsLayout]
2019-10-20 09:48:53.831308+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView setNeedsLayout]
2019-10-20 09:48:53.831640+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView setNeedsLayout]
2019-10-20 09:48:53.832722+0800 LayoutIfNeed[6081:2491415] -[TableCollectionViewController tableView:heightForRowAtIndexPath:]
2019-10-20 09:48:53.832866+0800 LayoutIfNeed[6081:2491415] -[ULTableView setNeedsLayout]
2019-10-20 09:48:53.833304+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView layoutSubviews]
2019-10-20 09:48:53.833478+0800 LayoutIfNeed[6081:2491415] -[UIInnerCollectionView numberOfSectionsInCollectionView:]
2019-10-20 09:48:53.833595+0800 LayoutIfNeed[6081:2491415] -[UIInnerCollectionView collectionView:numberOfItemsInSection:]
2019-10-20 09:48:53.835002+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-20 09:48:53.835350+0800 LayoutIfNeed[6081:2491415] -[UIInnerCollectionView collectionView:cellForItemAtIndexPath:]
2019-10-20 09:48:53.835618+0800 LayoutIfNeed[6081:2491415] -[ULCollectionView layoutSubviews] visibleCell 1
2019-10-20 09:48:53.835801+0800 LayoutIfNeed[6081:2491415] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 09:48:53.836383+0800 LayoutIfNeed[6081:2491415] -[TableCollectionViewController tableView:cellForRowAtIndexPath:] 0 1
2019-10-20 09:48:53.837371+0800 LayoutIfNeed[6081:2491415] -[TableCollectionViewController tableView:heightForRowAtIndexPath:]
2019-10-20 09:48:53.837523+0800 LayoutIfNeed[6081:2491415] -[ULTableView setNeedsLayout]
2019-10-20 09:48:53.838066+0800 LayoutIfNeed[6081:2491415] -[ULTableView setNeedsLayout]
2019-10-20 09:48:53.838735+0800 LayoutIfNeed[6081:2491415] -[ULTableView layoutSubviews]

根据上面的log 我们看到即使在页面加载的时候我们不主动调用reloadData页面也可以正常加载,是因为addsubview/init操作会触发layoutSubviews方法。这样即使没有reloadData页面也可以正常加载。

确认VisibleCell调用获取的数值

先确认下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)reloadVisibleCell {
NSLog(@"%s",__func__);
[self.tableView reloadData];
NSArray *tableViewVisibleCells = [self.tableView visibleCells];
NSLog(@"UITableView visibleCount%@",@(tableViewVisibleCells.count));
for (UITableViewCell *cell in tableViewVisibleCells) {
// cell 上加载内容的视图,对应可能是CollectionView
[cell.contentView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[UIInnerCollectionView class]]) {
UIInnerCollectionView *collectionView = (UIInnerCollectionView *)obj;
NSArray *array = [collectionView visibleCell];
NSLog(@"UIInnerCollectionView visibleCount%@",@(array.count));
}
}];
}
}

log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2019-10-20 10:57:19.462632+0800 LayoutIfNeed[6313:2513531] -[TableCollectionViewController reloadVisibleCell]
2019-10-20 10:57:19.462805+0800 LayoutIfNeed[6313:2513531] -[ULTableView reloadData]
2019-10-20 10:57:19.463147+0800 LayoutIfNeed[6313:2513531] -[TableCollectionViewController numberOfSectionsInTableView:]
2019-10-20 10:57:19.463397+0800 LayoutIfNeed[6313:2513531] -[ULTableView setNeedsLayout]
2019-10-20 10:57:19.463800+0800 LayoutIfNeed[6313:2513531] -[TableCollectionViewController tableView:numberOfRowsInSection:]
2019-10-20 10:57:19.464301+0800 LayoutIfNeed[6313:2513531] -[ULTableView setNeedsLayout]
2019-10-20 10:57:19.464657+0800 LayoutIfNeed[6313:2513531] -[ULTableView setNeedsLayout]
2019-10-20 10:57:19.464797+0800 LayoutIfNeed[6313:2513531] -[ULTableView setNeedsLayout]
2019-10-20 10:57:19.465240+0800 LayoutIfNeed[6313:2513531] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 10:57:19.465619+0800 LayoutIfNeed[6313:2513531] -[TableCollectionViewController tableView:cellForRowAtIndexPath:] 0 0
2019-10-20 10:57:19.466193+0800 LayoutIfNeed[6313:2513531] -[TableCollectionViewController tableView:heightForRowAtIndexPath:]
2019-10-20 10:57:19.466357+0800 LayoutIfNeed[6313:2513531] -[ULTableView setNeedsLayout]
2019-10-20 10:57:19.466656+0800 LayoutIfNeed[6313:2513531] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 10:57:19.466921+0800 LayoutIfNeed[6313:2513531] -[TableCollectionViewController tableView:cellForRowAtIndexPath:] 0 1
2019-10-20 10:57:19.467452+0800 LayoutIfNeed[6313:2513531] -[TableCollectionViewController tableView:heightForRowAtIndexPath:]
2019-10-20 10:57:19.467690+0800 LayoutIfNeed[6313:2513531] -[ULTableView setNeedsLayout]
2019-10-20 10:57:19.468489+0800 LayoutIfNeed[6313:2513531] -[ULTableView setNeedsLayout]
2019-10-20 10:57:19.468747+0800 LayoutIfNeed[6313:2513531] UITableView visibleCount2
2019-10-20 10:57:19.468898+0800 LayoutIfNeed[6313:2513531] UIInnerCollectionView visibleCount1

从上面的log我们可以看到,我们在reloadData后获取到的visibleCell都是正确的!

UICollectionView中嵌套UITableView

页面加载时

代码:

1
2
3
[self.view addSubview:self.collectionView];
NSArray *collectionViewVisibleCell = [self.collectionView visibleCells];
NSLog(@"UICollectionView visibleCount%@",@(collectionViewVisibleCell.count));

log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2019-10-20 11:12:00.989745+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.989925+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.990034+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.990269+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView reloadData]
2019-10-20 11:12:00.990395+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.990533+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.990894+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.991304+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.991690+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.992034+0800 LayoutIfNeed[6388:2521314] UICollectionView visibleCount0
2019-10-20 11:12:00.994969+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.995134+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.995228+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.995342+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.995465+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.995567+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.995673+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.995772+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:00.995894+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView setNeedsLayout]
2019-10-20 11:12:01.009260+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView layoutSubviews]
2019-10-20 11:12:01.009536+0800 LayoutIfNeed[6388:2521314] -[CollectionTableViewController numberOfSectionsInCollectionView:]
2019-10-20 11:12:01.009651+0800 LayoutIfNeed[6388:2521314] -[CollectionTableViewController collectionView:numberOfItemsInSection:]
2019-10-20 11:12:01.010533+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-20 11:12:01.010844+0800 LayoutIfNeed[6388:2521314] -[CollectionTableViewController collectionView:cellForItemAtIndexPath:]
2019-10-20 11:12:01.011126+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.012000+0800 LayoutIfNeed[6388:2521314] -[ULTableView reloadData]
2019-10-20 11:12:01.012172+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView numberOfSectionsInTableView:]
2019-10-20 11:12:01.012511+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:numberOfRowsInSection:]
2019-10-20 11:12:01.013372+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.015872+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView numberOfSectionsInTableView:]
2019-10-20 11:12:01.016756+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:numberOfRowsInSection:]
2019-10-20 11:12:01.017156+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView numberOfSectionsInTableView:]
2019-10-20 11:12:01.017900+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:numberOfRowsInSection:]
2019-10-20 11:12:01.018193+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.020487+0800 LayoutIfNeed[6388:2521314] -[ULCollectionView layoutSubviews] visibleCell 1
2019-10-20 11:12:01.021245+0800 LayoutIfNeed[6388:2521314] -[ULTableView layoutSubviews]
2019-10-20 11:12:01.021410+0800 LayoutIfNeed[6388:2521314] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 11:12:01.021747+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 0
2019-10-20 11:12:01.024221+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 11:12:01.024501+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.024982+0800 LayoutIfNeed[6388:2521314] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 11:12:01.025291+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 1
2019-10-20 11:12:01.025908+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 11:12:01.026027+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.026418+0800 LayoutIfNeed[6388:2521314] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 11:12:01.026711+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 2
2019-10-20 11:12:01.027502+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 11:12:01.027624+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.028011+0800 LayoutIfNeed[6388:2521314] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 11:12:01.028316+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 3
2019-10-20 11:12:01.029025+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 11:12:01.029192+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.029692+0800 LayoutIfNeed[6388:2521314] -[ULTableView dequeueReusableCellWithIdentifier:]
2019-10-20 11:12:01.030077+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:cellForRowAtIndexPath:] 0 4
2019-10-20 11:12:01.030814+0800 LayoutIfNeed[6388:2521314] -[UIInnerTableView tableView:heightForRowAtIndexPath:]
2019-10-20 11:12:01.030965+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.031518+0800 LayoutIfNeed[6388:2521314] -[ULTableView setNeedsLayout]
2019-10-20 11:12:01.032057+0800 LayoutIfNeed[6388:2521314] -[ULTableView layoutSubviews]
页面加载完成后

代码:

1
2
3
4
5
- (void)reloadVisibleCell {
[self.collectionView reloadData];
NSArray *collectionViewVisibleCell = [self.collectionView visibleCells];
NSLog(@"UICollectionView visibleCount%@",@(collectionViewVisibleCell.count));
}

log:

1
2
3
4
5
6
7
8
9
10
11
12
2019-10-20 11:15:40.370300+0800 LayoutIfNeed[6412:2522955] -[ULCollectionView reloadData]
2019-10-20 11:15:40.370570+0800 LayoutIfNeed[6412:2522955] -[ULCollectionView setNeedsLayout]
2019-10-20 11:15:40.370746+0800 LayoutIfNeed[6412:2522955] -[ULCollectionView setNeedsLayout]
2019-10-20 11:15:40.370893+0800 LayoutIfNeed[6412:2522955] -[ULCollectionView setNeedsLayout]
2019-10-20 11:15:40.371005+0800 LayoutIfNeed[6412:2522955] -[ULCollectionView setNeedsLayout]
2019-10-20 11:15:40.371120+0800 LayoutIfNeed[6412:2522955] -[ULCollectionView setNeedsLayout]
2019-10-20 11:15:40.371309+0800 LayoutIfNeed[6412:2522955] UICollectionView visibleCount0
2019-10-20 11:15:44.145073+0800 LayoutIfNeed[6412:2522955] -[ULCollectionView layoutSubviews]
2019-10-20 11:15:44.145280+0800 LayoutIfNeed[6412:2522955] -[CollectionTableViewController numberOfSectionsInCollectionView:]
2019-10-20 11:15:44.145406+0800 LayoutIfNeed[6412:2522955] -[CollectionTableViewController collectionView:numberOfItemsInSection:]
2019-10-20 11:15:44.146433+0800 LayoutIfNeed[6412:2522955] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-20 11:15:44.146820+0800 LayoutIfNeed[6412:2522955] -[CollectionTableViewController collectionView:cellForItemAtIndexPath:]
确认VisibleCell调用获取的数值

我们先看下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)reloadVisibleCell {
[self.collectionView reloadData];
NSArray *collectionViewVisibleCell = [self.collectionView visibleCells];
NSLog(@"UICollectionView visibleCount%@",@(collectionViewVisibleCell.count));
for (UICollectionViewCell *cell in collectionViewVisibleCell) {
// cell 上加载内容的视图,对应可能是CollectionView
[cell.contentView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[UIInnerTableView class]]) {
UIInnerTableView *tableView = (UIInnerTableView *)obj;
NSArray *array = [tableView visibleCell];
NSLog(@"UIInnerTableView visibleCount%@",@(array.count));
}
}];
}
}

然后我们在看下log

1
2
3
4
5
6
7
8
9
10
11
12
2019-10-20 11:08:33.397037+0800 LayoutIfNeed[6370:2519870] -[ULCollectionView reloadData]
2019-10-20 11:08:33.397305+0800 LayoutIfNeed[6370:2519870] -[ULCollectionView setNeedsLayout]
2019-10-20 11:08:33.397527+0800 LayoutIfNeed[6370:2519870] -[ULCollectionView setNeedsLayout]
2019-10-20 11:08:33.397721+0800 LayoutIfNeed[6370:2519870] -[ULCollectionView setNeedsLayout]
2019-10-20 11:08:33.397823+0800 LayoutIfNeed[6370:2519870] -[ULCollectionView setNeedsLayout]
2019-10-20 11:08:33.397913+0800 LayoutIfNeed[6370:2519870] -[ULCollectionView setNeedsLayout]
2019-10-20 11:08:33.398032+0800 LayoutIfNeed[6370:2519870] UICollectionView visibleCount0
2019-10-20 11:08:38.437912+0800 LayoutIfNeed[6370:2519870] -[ULCollectionView layoutSubviews]
2019-10-20 11:08:38.438140+0800 LayoutIfNeed[6370:2519870] -[CollectionTableViewController numberOfSectionsInCollectionView:]
2019-10-20 11:08:38.438250+0800 LayoutIfNeed[6370:2519870] -[CollectionTableViewController collectionView:numberOfItemsInSection:]
2019-10-20 11:08:38.489045+0800 LayoutIfNeed[6370:2519870] -[ULCollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:]
2019-10-20 11:08:38.489259+0800 LayoutIfNeed[6370:2519870] -[CollectionTableViewController collectionView:cellForItemAtIndexPath:]

从上面的log我们可以看出,reloadData之后 因为collectionView并没有调用layoutIfNeed所以在这之后无法获取到visibleCell,所以肯定不会影响到内部的TableView所以获取TableView的visibleCell肯定也是无效的。

未完待续…