Reputation: 1564
UITableView
provides the methods indexPathsForVisibleRows
and visibleCells
, but how can I get the visible sections?
Upvotes: 18
Views: 21784
Reputation: 2901
Swift 4 and Swift 5
We can do the following since an empty section could still have a visible header view:
extension UITableView {
var indexesOfVisibleSections: [Int] {
var indexes = [Int]()
(0 ..< numberOfSections).forEach {
let headerRect = (style == .plain ?
rect(forSection: $0) :
rectForHeader(inSection: $0))
// The "visible part" of the tableView is based on the
// content offset and the tableView's size.
let visiblePartOfTableView =
CGRect(x: contentOffset.x, y: contentOffset.y,
width: bounds.size.width, height: bounds.size.height)
if (visiblePartOfTableView.intersects(headerRect)) {
indexes.append($0)
}
}
return indexes
}
}
Upvotes: 0
Reputation: 15978
Have you tried this in Swift 4?
let sections = tableView.indexPathsForVisibleRows?.map { $0.section } ?? []
for section in sections {
print(String(format: "%d", section))
}
Upvotes: -1
Reputation: 5569
self.sections.indices.forEach{ (i:Int) in
let section:UIView? = self.tableView(self, viewForHeaderInSection: i)
}
Upvotes: 0
Reputation: 3803
Swift version
if let visibleRows = tableView.indexPathsForVisibleRows {
let visibleSections = visibleRows.map({$0.section})
}
Upvotes: 13
Reputation: 529
for (NSUInteger section = 0; section < self.tableView.numberOfSections; ++section) {
UIView *headerView = [self.tableView headerViewForSection:section];
if (headerView.window) {
NSLog(@"its visible");
}
}
Upvotes: 1
Reputation: 1673
Answer is a lot simpler and neater with kvc
NSArray *visibleSections = [self.tableView.indexPathsForVisibleRows valueForKey:@"section"];
this might give you an array with duplicate values but you can manage from there.
Upvotes: 1
Reputation: 1298
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];
}
Upvotes: 1
Reputation: 1715
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.
Upvotes: 23
Reputation: 1564
I have got the solution.
First step, each section will show a UIView that created by - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
, that will be stored into array.
When the TableView is scrolled , I want free the invisible section view, so I need know which section is visible or not, follow function code will detect for this purpose, if the view is visible then free it.
-(BOOL)isVisibleRect:(CGRect)rect containerView:(UIScrollView*)containerView
{
CGPoint point = containerView.contentOffset;
CGFloat zy = point.y ;
CGFloat py = rect.origin.y + rect.size.height;
if (py - zy <0) {
return FALSE;
}
CGRect screenRect = containerView.frame;
CGFloat by = screenRect.size.height + zy ;
if (rect.origin.y > by) {
return FALSE;
}
return TRUE;
}
(rect
is the frame of the section UIView
; containerView
is the UITableView
)
In this way, I can get visible sections of the UITableView
, but I hope the SDK can provide API for this purpose directly.
Upvotes: 1
Reputation: 1
another solution, use 1 bit in your section header view's tag, like that
#define _TBL_TAG_SECTION(_TAG) ((_TAG)|(1<<30))
#define _TBL_TAG_CLEAR(_TAG) ((_TAG)&((1<<30)-1))
#define _TBL_TAG_IS_SECTION(_TAG) ((_TAG)>>30)
- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
// alloc header view
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
header.tag = _TBL_TAG_SECTION(section);
return header;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGRect r = CGRectMake(scrollView.contentOffset.x, scrollView.contentOffset.y,
CGRectGetWidth(scrollView.frame),
CGRectGetHeight(scrollView.frame));
for (UIView *v in [_tableView subviews]) {
if ( CGRectIntersectsRect(r, v.frame) ) {
if ( _TBL_TAG_IS_SECTION(v.tag) ) {
NSLog(@"visible section tag %d", _TBL_TAG_CLEAR(v.tag));
}
}
}
}
Upvotes: 0
Reputation: 2699
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 )}
Upvotes: 2
Reputation: 986
UITableViews store their cells using an NSIndexPath. As a result there is no object for sections. Using the following code we can traverse the table and perform operations using the indexes of visible sections (I'm not sure why you want visible sections since visible only means they are currently on the screen, but whatever).
for (NSIndexPath* i in [yourTableViewName indexPathsForVisibleRows])
{
NSUInteger sectionPath = [i indexAtPosition:0];
//custom code here, will run multiple times per section for each visible row in the group
}
Upvotes: 8