PDA

View Full Version : Expand/Collapse TableView Sections




nashyo
Aug 26, 2012, 04:58 AM
This isn't working as expected. The App becomes completely unresponsive and freezes as soon as I attempt to press the UIButton in the sectionHeaderView.

The button works when it it's target method returns nil so it's definitely the method i have set up as it's target/action.

Where am I going wrong here?

@interface ListViewController ()
@property (nonatomic, strong) NSMutableArray *tableViewIndexPaths;
@property (nonatomic, strong) NSMutableArray *toggleFlags;
@end

@implementation VAListViewController {
NSInteger sectionButton;
}

@synthesize tableViewIndexPaths = _tableViewIndexPaths;
@synthesize toggleFlags = _toggleFlags;

-(NSMutableArray*)tableViewIndexPaths
{
if (_tableViewIndexPaths == nil) {
_tableViewIndexPaths = [[NSMutableArray alloc] init];
}
return _tableViewIndexPaths;
}

-(NSMutableArray*)toggleFlags
{
if (_toggleFlags == nil) {
_toggleFlags = [[NSMutableArray alloc] init];
}
return _toggleFlags;
}

-(UIButton*)generateExpandCollapseButtonForHeaderView // Called and frame set in viewForHeaderInSection
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.tag = sectionButton++;
[button addTarget:self action:@selector(sectionExpandCollapseButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
return button;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";

[self.tableViewIndexPaths addObject:indexPath];
BOOL isSectionExpanded = NO;
[self.toggleFlags addObject:[NSNumber numberWithBool:isSectionExpanded]];

...........some other stuff
}

-(void)sectionExpandCollapseButtonPressed:(UIButton*)sender
{
if (![sender isKindOfClass:[UIButton class]]) {
NSLog(@"Sender is not a button");
}

NSMutableArray *tmpArray = [NSMutableArray array];
NSInteger rows = [self.tableView numberOfRowsInSection:sender.tag];
int i;
BOOL toggleFlag = [[self.toggleFlags objectAtIndex:sender.tag] boolValue];
BOOL isSectionExpanded = !toggleFlag;
[self.toggleFlags removeObjectAtIndex:sender.tag];
[self.toggleFlags insertObject:[NSNumber numberWithBool:isSectionExpanded] atIndex:sender.tag];

if (isSectionExpanded)
{
for (i=0; i<rows; i++) {
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:sender.tag];
[tmpArray addObject:tmpIndexPath];
}
[self.tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
} else
{
for (i=0; i<rows; i++) {
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:sender.tag];
[tmpArray addObject:tmpIndexPath];
}
[self.tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
}
}



jnoxx
Aug 26, 2012, 01:26 PM
There is code for this on Maniacdev website, I coded one myself which does that, but maybe you could use his component (there are severals there) :)

xStep
Aug 26, 2012, 01:35 PM
I'm not fully in the coding frame of mind right now, but here are some thoughts...

We don't know where generateExpandCollapseButtonForHeaderView is called from so we don't know it's influence.

I'm curious why when the isSectionExpanded is true, you are deleting rows, and the opposite otherwise. Seems counter intuitive to my thinking of what should be occurring.

You are continuously added 1 to sectionButton and button.tag. I suspect that at some point that number will be greater than what you are tracking unless you are doing subtraction somewhere else.

Perhaps return zero from numberOfRowsInSection when you don't want to display those rows. With zero returned I think tableView:cellForRowAtIndexPath: will not be called then for that section, thereby not displaying the detail.

If the app is not crashing but is unresponsive, odds are you have some endless loop and/or blocking the main thread. Spread some NSLog()s around to see what is up.