UITableView
provides the methods indexPathsForVisibleRows
and visibleCells
, but how can I get the visible sections?
Swift version
if let visibleRows = tableView.indexPathsForVisibleRows {
let visibleSections = visibleRows.map({$0.section})
}
Swift 4 and Swift 5
extension UITableView {
func returnVisibleCellsIndexes() -> [IndexPath] {
var indexes = [IndexPath]()
for cell in self.visibleCells {
if let indexpath = self.returnIndexPath(cell: cell) {
indexes.append(indexpath)
}
}
return indexes
}
func returnIndexPath(cell: UITableViewCell) -> IndexPath?{
guard let indexPath = self.indexPath(for: cell) else {
return nil
}
return indexPath
}
func returnVisibleCells() -> [UITableViewCell]{
let visiblecell = self.visibleCells
return visiblecell
}
}
How to use
let visibleCellsIndexes = self.tableView.returnVisibleCellsIndexes()
visibleCellsIndexes.forEach { (indexpath) in
print(indexpath.section)
}
for (NSUInteger section = 0; section < self.tableView.numberOfSections; ++section) {
UIView *headerView = [self.tableView headerViewForSection:section];
if (headerView.window) {
NSLog(@"its visible");
}
}
Or the really easy way would be to take advantage of valueForKeyPath and the NSSet class:
NSSet *visibleSections = [NSSet setWithArray:[[self.tableView indexPathsForVisibleRows] valueForKey:@"section"]];
Basically you get an array of the section values in the visible rows and then populate a set with this to remove duplicates.
Extract the sections from the list of visible rows:
NSArray *indexPathsForVisibleRows = [tableView indexPathsForVisibleRows];
NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
for ( NSIndexPath *indexPath in indexPathsForVisibleRows ) {
[indexSet addIndex:indexPath.section];
}
NSLog(@"indexSet %@",indexSet);
// indexSet <NSMutableIndexSet: 0x11a5c190>[number of indexes: 5 (in 1 ranges), indexes: (9-13)]
Or:
NSArray *indexPathsForVisibleRows = [detailTableView indexPathsForVisibleRows];
NSMutableSet *sectionSet = [NSMutableSet set];
for ( NSIndexPath *indexPath in indexPathsForVisibleRows ) {
[sectionSet addObject:[NSNumber numberWithInt:indexPath.section]];
}
NSLog(@"sectionSet %@",sectionSet);
// sectionSet {(13, 11, 9, 10, 12 )}
2 step solution to get the visible sections in a UITableView:
1) Add the header views to a mutable array in viewForHeaderInSection
2) Update the array when the tableview scrolls in scrollViewDidScroll
note the use of the tag property to hold the section number
@property (nonatomic, strong, readwrite) NSMutableArray *headerArray;
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 40)];
headerView.backgroundColor = [UIColor greenColor];
headerView.tag = section;
[_headerArray addObject:headerView];
return headerView;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self updateHeaderArray];
NSLog(@"------------");
for (UIView *view in _headerArray) {
NSLog(@"visible section:%d", view.tag);
}
}
- (void)updateHeaderArray {
// remove invisible section headers
NSMutableArray *removeArray = [NSMutableArray array];
CGRect containerRect = CGRectMake(_tableView.contentOffset.x, _tableView.contentOffset.y,
_tableView.frame.size.width, _tableView.frame.size.height);
for (UIView *header in _headerArray) {
if (!CGRectIntersectsRect(header.frame, containerRect)) {
[removeArray addObject:header];
}
}
[_headerArray removeObjectsInArray:removeArray];
}