UITableView节标题和节页脚不更新(重绘问题)

时间:2010-04-26 13:43:07

标签: iphone uitableview

更新4.0

似乎iOS 4.0在这里改变了一些东西。根据我的第一次快速检查,相同的代码在所描述的场景中为节标题生成了错误的背景!

原始

我有一个UITableView分组样式,带有自定义页眉和页脚视图。在页脚里面我放了一个UILabel和一个UIButton。

单击按钮隐藏或显示一些行,更新页脚视图中的UILabel,最后调整页脚视图的大小。

基本上一切都运转正常。但是文本离开标签没有在屏幕上更新。它在UILabel文本属性中更新,但只有当我将部分页脚滚动到可见区域之外并向后滚动它时,它才会更新。所以这是UITableView的典型重绘问题。

我尝试了各种方法强制更新,例如needsLayout等。没有任何帮助。

我已经看到了一些相关的问题,但有一些不同的行为,没有解决方案。任何帮助/想法?

谢谢,Gerd

更新:

部分页脚出现问题,所以这是我的viewForFooterInSection。

基本上我想折叠/展开一个部分,但不是完全(这是一件容易的事)而只是空单元格(ItemSize为空)。如果它是折叠的,则footerView很大,如果它被展开则会缩小。此外,标签文字也会改变。

- (UIView *)tableView: (UITableView *)tableView viewForFooterInSection: (NSInteger)section{
NSLog(@"viewForFooterInSection section:%i", section);

UIButton *myView;
UILabel *label;

if ([[[self.sectionStatus objectAtIndex:section] valueForKey:@"collapseStatus"] isEqual:@"collapse"]){ 
    myView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 52)];
    [myView setBackgroundImage:[UIImage imageNamed:@"ItemViewFooter.png"] forState:UIControlStateNormal];
    label = [[UILabel alloc] initWithFrame:CGRectMake(20, 32, 300, 20)];
    label.text = NSLocalizedString(@"list_expand",@"");
} else { //is expanded
    myView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
    [myView setBackgroundImage:[UIImage imageNamed:@"ListCollapseExpand.png"] forState:UIControlStateNormal];
    label = [[UILabel alloc] initWithFrame:CGRectMake(20, 1, 300, 20)];
    label.text = NSLocalizedString(@"list_collapse",@"");
}

myView.tag=section;
[myView addTarget:self action:@selector(collapseExpandAction:) forControlEvents:UIControlEventTouchUpInside];
myView.backgroundColor = [UIColor clearColor];
myView.adjustsImageWhenHighlighted = NO;
myView.showsTouchWhenHighlighted = YES;

label.textColor = FONTCOLOR;
label.font = [UIFont systemFontOfSize:14];
label.numberOfLines = 1;
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
[myView addSubview:label];
return myView;

};

在按钮操作方法中,我存储了部分折叠/展开的状态和显示的行数。比我删除或插入行。 (必须使用插入/删除,因为我需要动画)。

- (void) collapseExpandSection: (NSInteger) section{
NSMutableArray *paths = [NSMutableArray arrayWithCapacity:10];
NSInteger row;
NSInteger numberOfDisplayedItems=[[[self.sectionStatus objectAtIndex:section] valueForKey:@"numberOfDisplayedRows"] intValue];
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
NSInteger numberOfAllItems=[sectionInfo numberOfObjects];
Item *tmpItem=nil;
NSSet *itemsWithSizes=nil;

//filter not used cells
for ( row = 0; row < numberOfAllItems; row++ ) {
    tmpItem=[fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:row inSection:section]];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"itemSize != nil"];
    NSSet *itemsWithSizes = [tmpItem.itemSizes filteredSetUsingPredicate:predicate];
    if ([itemsWithSizes count]==0){ 
        [paths addObject:[NSIndexPath indexPathForRow:row inSection:section]]; //all unused cells
    };
}

if (numberOfDisplayedItems == numberOfAllItems){ //currently all shown => Collapse
    [self.tableView beginUpdates];
    [[self.sectionStatus objectAtIndex:section] setValue:[NSNumber numberWithInt:(numberOfDisplayedItems-[paths count])] forKey:@"numberOfDisplayedRows"];
    [[self.sectionStatus objectAtIndex:section] setValue:@"collapse" forKey:@"collapseStatus"];
    [self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView endUpdates];
} else { //Not all shown so expand with the unused cells
    [[self.sectionStatus objectAtIndex:section] setValue:[NSNumber numberWithInt:(numberOfDisplayedItems+[paths count])] forKey:@"numberOfDisplayedRows"];
    [[self.sectionStatus objectAtIndex:section] setValue:@"expand" forKey:@"collapseStatus"];
    [self.tableView beginUpdates];
    [self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView endUpdates];
}
return;

};

一切都做得很好。块开始/结束更新后,将为每个部分调用viewForFooter,并在属性中设置正确的标签文本。但是显示无法正确更新。一旦强制重新显示(滚动滚动),显示就可以了。

3 个答案:

答案 0 :(得分:4)

有2个问题 第一个问题是部分页脚没有更新。 更新后请尝试拨打[tableView reloadData][tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade](可能是dalay) 第二个问题是myViewlabel中的内存泄漏。 另外,为什么在使用按钮的内部标签时会使用标签? 附:不要直接分配UIButton对象,因为它是工厂的。请改为呼叫[UIButton buttonWithType:UIButtonTypeCustom]

更新:更新的另一种方法是通过访问页脚视图直接更新页脚。

- (void) collapseExpandSection: (NSInteger) section{

检查该部分是否真的是您的按钮

 - (void) collapseExpandSection: (UIButton*) sender{
// Do update of sender here
// Do other stuff
}

您还可以尝试下一个技巧:在委托中创建UIView对象,在其上添加按钮和标签,然后返回对象视图本身的实例。

答案 1 :(得分:3)

我的问题是我正在扩展Section标题以显示搜索栏,但在我滚动UITableView之前它不会重绘视图。

我有自己的SectionHeader类,它将UIView子类化并控制搜索内容。

在我的动画之后,我只是用它来强制更新。它不漂亮,但它有效。

CGPoint point = CGPointMake(((UIScrollView *)self.superview).contentOffset.x,
                            ((UIScrollView *)self.superview).contentOffset.y+1);
[((UIScrollView *)self.superview) setContentOffset:point animated:NO];

point = CGPointMake(((UIScrollView *)self.superview).contentOffset.x, 
                    ((UIScrollView *)self.superview).contentOffset.y-1);
[((UIScrollView *)self.superview) setContentOffset:point animated:NO];

基本上强制UITableView向下滚动1个像素,向上滚动1个像素。

答案 2 :(得分:0)

I had an issue just like this where I wanted to update the section header after inserting a new row. I found that calling tableView reloadSections() method with an animation setting of .None after I call the insertRows method worked for me (both calls in the same tableView update block). I got the insert animation I wanted and also the section header was updated.