如何更新/重新加载/刷新UITableView中的节头视图?

时间:2012-08-09 18:29:54

标签: uitableview header

当我点击一行时,我愿意更改我的UITableView的特定标题视图。

我已经阅读了所有帖子。我尝试了#34; reloadData"," setNeedDisplay"," reloadSections:withRowAnimation:"以及其他一些想法......没有什么可做的。我的标题视图要么不更新,要么只有在我移动表格视图时才会更新(这不是我愿意实现的)。

我的代码现在看起来像这样(关于UITableView委托方法):

-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {
    if(tableView==_storeTableView){
        return [_storeDataArray count];
    } else {
        return 1;
    }
}

-(UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section {
    if(tableView==_storeTableView){
        HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:section];
        if (!headerModel.headerView) {
            NSString *shelfName = headerModel.shelf;
            headerModel.headerView = [[[HouraStoreHeaderView alloc] initWithFrame:CGRectMake(0.0, 0.0, _storeTableView.bounds.size.width, 80) title:shelfName section:section subheaderNumber:([headerModel.openedSubHeaders count]-1) delegate:self] autorelease];
        }
        return headerModel.headerView;
    } else {
        return nil;
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if(tableView==_storeTableView){
        HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:section];
        NSDictionary *myDict = _storeDataDict;
        for (NSInteger i = 0; i < [headerModel.openedSubHeaders count]; i++) {
            myDict = [myDict objectForKey:[headerModel.openedSubHeaders objectAtIndex:i]];
        }
        NSInteger numberOfRowsInSection = [[myDict allKeys] count];
        return headerModel.open ? numberOfRowsInSection : 0;
    } else if(tableView==_searchTableView){
        return [_resultArray count];
    } else {
        return 0;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }
    if(tableView==_storeTableView){
        HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:indexPath.section];
        NSDictionary *myDict = _storeDataDict;
        for (NSInteger i = 0; i < [headerModel.openedSubHeaders count]; i++) {
            myDict = [myDict objectForKey:[headerModel.openedSubHeaders objectAtIndex:i]];
        }
        cell.accessoryView=[[[HouraStoreCellView alloc] initWithFrame:CGRectMake(0.0, 0.0, _storeTableView.bounds.size.width, 50) title:[[myDict allKeys] objectAtIndex:indexPath.row]] autorelease];
        return cell;
    } else if (tableView==_searchTableView) {
        cell.textLabel.text = [_resultArray objectAtIndex:indexPath.row];
        return cell;
    } else {
        return cell;
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:section];
    NSInteger height = 59.0 + ([headerModel.openedSubHeaders count]-1)*41.0;
    return height;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if(tableView==_storeTableView){
        HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:indexPath.section];
        NSDictionary *myDict = _storeDataDict;
        for (NSInteger i = 0; i < [headerModel.openedSubHeaders count]; i++) {
            myDict = [myDict objectForKey:[headerModel.openedSubHeaders objectAtIndex:i]];
        }
        if ([[myDict objectForKey:[[myDict allKeys] objectAtIndex:indexPath.row]] isKindOfClass:[NSDictionary class]]) {
            [self cellOpened:indexPath];
        } else {
            [_activityIndicatorView startAnimating];
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(_listProductsFoundedFinished:)
                                                         name:HouraSearchProductsDone
                                                       object:nil]; 
            NSString *searchString = [[myDict allKeys] objectAtIndex:indexPath.row];
            searchString = [searchString stringByReplacingOccurrencesOfString:@"\"" withString:@"\\u0022"];
            [_singleton.util beginSearchProducts:searchString context:@"2"];
        }
    } else if(tableView==_searchTableView){
        _searchBar.text = [_resultArray objectAtIndex:indexPath.row];

        [_searchBar resignFirstResponder];
        [_activityIndicatorView startAnimating];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(_listProductsFoundedFinished:)
                                                     name:HouraSearchProductsDone
                                                   object:nil]; 
        [_singleton.util beginSearchProducts:_searchBar.text context:@"2"];
    }
}

-(void)headerView:(HouraStoreHeaderView*)headerView headerOpened:(NSInteger)headerOpened {
    if (self.openSectionIndex!=NSNotFound) {
        [self closeAllHeaders];
    }
        //[self closeAllHeaders];
    HouraStoreHeaderModel *headerModel =nil;

    headerModel = [self.headerInfoArray objectAtIndex:headerOpened];
    headerModel.open = YES;
    headerModel.headerView.disclosureButton.selected = YES;

    NSDictionary *myDict = _storeDataDict;
    for (NSInteger i = 0; i < [headerModel.openedSubHeaders count]; i++) {
        myDict = [myDict objectForKey:[headerModel.openedSubHeaders objectAtIndex:i]];
    }
    NSInteger countOfRowsToInsert = [[myDict allKeys] count];

    NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init];
    for (NSInteger i = 0; i < countOfRowsToInsert; i++) {
        [indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:headerOpened]];
    }

    NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];

    NSInteger previousOpenSectionIndex = self.openSectionIndex;
    if (previousOpenSectionIndex != NSNotFound) {

        HouraStoreHeaderModel *previousHeaderModel = [self.headerInfoArray objectAtIndex:previousOpenSectionIndex];
        previousHeaderModel.open = NO;
        previousHeaderModel.headerView.disclosureButton.selected = NO;
        [previousHeaderModel.headerView toggleOpenWithUserAction:NO];
        NSInteger countOfRowsToDelete = [[[_storeDataDict objectForKey:previousHeaderModel.shelf ] allKeys] count];
        for (NSInteger i = 0; i < countOfRowsToDelete; i++) {
            [indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:previousOpenSectionIndex]];
        }
    }
    UITableViewRowAnimation insertAnimation;
    UITableViewRowAnimation deleteAnimation;
    if (previousOpenSectionIndex == NSNotFound || headerOpened < previousOpenSectionIndex) {
        insertAnimation = UITableViewRowAnimationTop;   
        deleteAnimation = UITableViewRowAnimationBottom;
    } else {
        insertAnimation = UITableViewRowAnimationBottom;
        deleteAnimation = UITableViewRowAnimationTop;
    }

    [_storeTableView beginUpdates];
    [_storeTableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:deleteAnimation];
    [_storeTableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:insertAnimation];
    [_storeTableView endUpdates];

    self.openSectionIndex = headerOpened;
}

-(void)headerView:(HouraStoreHeaderView*)headerView headerClosed:(NSInteger)headerClosed {

    HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:headerClosed];

    headerModel.open = NO;
    headerModel.headerView.disclosureButton.selected = NO;
    [headerModel cleanOpenedSubHeaders];
    [self.headerInfoArray replaceObjectAtIndex:headerClosed withObject:headerModel];

    NSInteger countOfRowsToDelete = [_storeTableView numberOfRowsInSection:headerClosed];

    if (countOfRowsToDelete > 0) {
        NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
        for (NSInteger i = 0; i < countOfRowsToDelete; i++) {
            [indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:headerClosed]];
        }
        [_storeTableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationTop];
    }
    self.openSectionIndex = NSNotFound;
}

-(void)cellOpened:(NSIndexPath*)indexPath {
    HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:indexPath.section];
    [self headerView:headerModel.headerView headerClosed:indexPath.section];
    [headerModel addOpenedSubHeaders:[[[_storeDataDict objectForKey:headerModel.shelf] allKeys] objectAtIndex:indexPath.row]];
    [self.headerInfoArray replaceObjectAtIndex:indexPath.section withObject:headerModel];
    headerModel = [self.headerInfoArray objectAtIndex:indexPath.section];
    [self headerView:headerModel.headerView headerOpened:indexPath.section];
}

-(void)closeAllHeaders {
    for (NSInteger i = 0; i < [self.headerInfoArray count]; i++) {
        HouraStoreHeaderModel *headerModel = [self.headerInfoArray objectAtIndex:i];
        [self headerView:headerModel.headerView headerClosed:i];
    }
}

我想要做的是,当我点击一行时,部分标题更新,因此它包含一个带有行文本的新按钮。然后我关闭该行并在节行中重新加载新数据。我设法完美地处理了这些行。但我无法找到更新此标题视图的方法。

任何想法都可以。

2 个答案:

答案 0 :(得分:2)

您只需直接更改即可。我在头文件中为标签创建了一个实例变量,我将把它放在我将创建的标题视图中:

@interface MainViewController : UITableViewController {
    // creating my datasource array instance variable
    NSArray *_items;

    // this is the label I will add to the header view when I create it
    UILabel *_headerLabel;
}

@end

在我的tableView中,当他们选择一行时,我调用的函数只是更改了标签上的文字:

@implementation MainViewController

- (id)init {
    self = [super initWithStyle:UITableViewStyleGrouped];

    / filling my datasource with test strings
    _items = @[@"one", @"two"];

    return self;
}

- (void)changeHeaderLabel:(NSString *)newLabel {
    // when this function gets called and is passed a string, I will simply
    // set the text on the label to the new string and viola!
    _headerLabel.text = newLabel;
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // this table will only have a single section for demo purposes
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // return the count of my datasource array
    return _items.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // attempt to create a cell by reusing one with a given identifier
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

    // if I wasn't able to reuse one
    if (cell == nil) {
        // create one from scratch with that identifier
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }

    // now simply set the text on the cell from my data source array of strings
    cell.textLabel.text = _items[indexPath.row];

    // and return the cell
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // deselect the row so the cell automatically fades out after selection
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    // here you could do one of two things, either get a reference to the cell itself,
    // and then get the value stored in it's textLabel
    UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
    NSString *newHeaderTitleString = selectedCell.textLabel.text;

    // OR you can get it right from your datasource
    NSString *newHeaderTitleString = _items[indexPath.row];

    // then just call the above function with the string as the single param
    [self changeHeaderLabel:newHeaderTitleString];
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    // here I just create a view that will span the whole frame and is an arbitrary height
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 80)];
    // set the background color to clear
    headerView.backgroundColor = [UIColor clearColor];

    // then I initialize my instance variable with a frame that's centered in the view
    // for aesthetic purposes
    _headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, self.view.frame.size.width - 10, 80)];

    // then I set the text color, add an autoresizing mask so if the view rotates
    // it still remains centered properly, set the text to some starting value, 
    // and add it to the headerView I previously created
    _headerLabel.textColor = [UIColor darkGrayColor];
    _headerLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    _headerLabel.text = @"Before";
    [headerView addSubview:_headerLabel];

    // then I return the headerView
    return headerView;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    // return an arbitrary height here for testing
    return 80;
}

结果如下:

enter image description here

enter image description here enter image description here

如果您有任何疑问,请告诉我们!这只是一个演示它的快速示例,但您可能希望以不同的方式自定义视图。这应该至少可以解决您的问题并为您提供一个起点。

答案 1 :(得分:1)

您是否尝试reloadRowsAtIndexPaths:withRowAnimation:row的{​​{1}}属性设置为NSIndexPath?因此,重新加载第3节的标题,例如看起来像

NSNotFound

我什么都不保证,但我很确定以前曾经工作过,因为我曾经使用过几次。

但即使它有效,它仍然是一个可能随时被苹果打破的黑客。

修改

好的,没关系。我在Xcode 5中尝试使用iOS 7,出于某种原因,即使使用NSIndexPath * headerIndexPath = [NSIndexPath indexPathForRow: NSNotFound section:3]; [self.tableView reloadRowsAtIndexPaths:@[headerIndexPath] withRowAnimation: UITableViewRowAnimationAutomatic]; 作为行号,它仍会重新加载整个部分(包含其所有单元格)。所以这不再适用了,该死的。