开发者

Button added to custom section header view disappears when row is deleted

开发者 https://www.devze.com 2023-01-31 04:01 出处:网络
Just came across some very strange behavior in my app. I\'ve recreated the problem in a simplest-case scenario:

Just came across some very strange behavior in my app. I've recreated the problem in a simplest-case scenario:

NSMutableArray *data;

- (void)viewDidLoad {
    [super viewDidLoad];
    data = [[NSMutableArray arrayWithObjects:@"1", @"2", @"3", nil] retain];
}

- (UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger)section { 
    UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 32.0)];
    header.backgroundColor = [UIColor lightGrayColor];
    [header addSubview:self.button];
    return header;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingS开发者_如何学编程tyle == UITableViewCellEditingStyleDelete) {    
        [data removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return data.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
    cell.textLabel.text = [data objectAtIndex:indexPath.row];
    return cell;
}

- (void)dealloc {
    [super dealloc];
}

Every time I delete a row; the button in my header disappears! This happens no matter what type of rowAnimation I use. If I scroll the table up so that the header scrolls off; the button returns when the header returns. The button is created in the xib file.

I can work around it in one of 2 ways:

  • Reloading the tableView data after the delete; with a delay so that the deletion animation completes first.

  • Creating the button in viewForHeaderInSection instead of in the interfaceBuilder.

    I'd really like to understand what's going on here. Where is the button going? I've confirmed that viewForHeaderInSection is called when I delete a row.

Edit I tried changing it so that the button is created in viewForHeader, instead of in the xib, but it's causing other strange issues... when I create or delete the button, I am setting certain properties such as the title and enabled depending on how many items there are in the table. When I delete the last row in the table, I don't see the update in text and enabled status until I scroll the button off the screen and back on again.


Because you only have one instance of your button, if the table view decides to create a new header view then the button will be removed from its current parent and moved to the new one. Even if you only have one section in your table, the table view may be doing some strange things internally and recreating header views off-screen so you can't rely on just one being in existence at any one time.

You should create the button in viewForHeaderInSection: and work around your other problems. Rather than only updating the button properties in viewForHeaderInSection you should handle any delete events so that deleting a row will also update the button.


Where is your implementation of the delegate method tableView:heightForHeaderInSection: ? That is necessary for tableView:viewForHeaderInSection: to work correctly. Check the docs. Reference for UITableView delegate

I've confirmed that viewForHeaderInSection is called when I delete a row.

Have you confirmed that viewForHeaderInSection is called for the particular header with the added button? Then, try adding

[header bringSubviewToFront:self.button];  

after adding the button.


Well I at least managed to get around my issue... I made an iVar and property for the view that I create in viewForheaderAtSection, and then I only create a new view if I don't have one already. Otherwise I just return the header I already had; something like this:

- (UIView *)tableView:(UITableView *)aTableView viewForHeaderInSection:(NSInteger)section { 
    if (!self.myHeader){
        UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, 32.0)];
        header.backgroundColor = [UIColor lightGrayColor];
        [header addSubview:self.button];
        self.myHeader = header;
        [header release];
    }
    return self.myHeader;
}

This works, but it would still be great to understand what exactly is going on. As far as I can tell, viewForHeaderInSection is being called by the system, but then the instance of the view that I return in that method is not actually being used / shown; at least not until I do something that causes the view to redraw...

0

精彩评论

暂无评论...
验证码 换一张
取 消