这是另一个对我有用的选择。在 viewForFooter 委托方法中,检查它是否是最后一部分,并在那里添加代码。这种方法是在意识到 will DisplayCell 不会计算页脚(如果你有页脚的话)之后想到的。
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
// Perform some final layout updates
if (section == ([tableView numberOfSections] - 1)) {
[self tableViewWillFinishLoading:tableView];
}
// Return nil, or whatever view you were going to return for the footer
return nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
// Return 0, or the height for your footer view
return 0.0;
}
- (void)tableViewWillFinishLoading:(UITableView *)tableView
{
NSLog(@"finished loading");
}
- (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL isFinishedLoadingTableView = [self isFinishedLoadingTableView:tableView
indexPath:indexPath];
if (isFinishedLoadingTableView) {
NSLog(@"end loading");
}
}
- (BOOL)isFinishedLoadingTableView:(UITableView *)tableView
indexPath:(NSIndexPath *)indexPath
{
// The reason we cannot just look for the last row is because
// in iOS7.0x the last row is updated before
// looping through all the visible rows in ascending order
// including the last row again. Strange but true.
NSArray * visibleRows = [tableView indexPathsForVisibleRows]; // did verify sorted ascending via logging
NSIndexPath *lastVisibleCellIndexPath = [visibleRows lastObject];
// For tableviews with multiple sections this will be more complicated.
BOOL isPreviousCallForPreviousCell =
self.previousDisplayedIndexPath.row + 1 == lastVisibleCellIndexPath.row;
BOOL isLastCell = [indexPath isEqual:lastVisibleCellIndexPath];
BOOL isFinishedLoadingTableView = isLastCell && isPreviousCallForPreviousCell;
self.previousDisplayedIndexPath = indexPath;
return isFinishedLoadingTableView;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// cancel the perform request if there is another section
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(tableViewDidLoadRows:) object:tableView];
// create a perform request to call the didLoadRows method on the next event loop.
[self performSelector:@selector(tableViewDidLoadRows:) withObject:tableView afterDelay:0];
return [self.myDataSource numberOfRowsInSection:section];
}
// called after the rows in the last section is loaded
-(void)tableViewDidLoadRows:(UITableView*)tableView{
self.cellsAreLoaded = YES;
}
一个可能的更好的设计是将可见单元格添加到一个集合中,然后当需要检查表是否已加载时,可以改为围绕这个集合执行 for 循环,例如。
var visibleCells = Set<UITableViewCell>()
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
visibleCells.insert(cell)
}
override func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
visibleCells.remove(cell)
}
// example property you want to show on a cell that you only want to update the cell after the table is loaded. cellForRow also calls configure too for the initial state.
var count = 5 {
didSet {
for cell in visibleCells {
configureCell(cell)
}
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
// perform your logic here, for the first row in the table
}
// ....
}