Iphone 通过cell.contentView将UIView添加到UITableViewCell

Iphone 通过cell.contentView将UIView添加到UITableViewCell,iphone,ios,uitableview,Iphone,Ios,Uitableview,我有一个叫做GraphView的类,它扩展了UIView,基本上画了一个小折线图。在我的UITableView中,我需要在每个部分的顶部有一个这样的图。因此,我尝试在我的一个部分顶部创建一个单独的单元格,然后在该单元格上: [cell.contentView addSubview:graphView]; [graphView release]; 但当我向下滚动时,它就像是一个闪烁的图形,它显示在UITableView的随机点上。有人有想法或见解吗?是否有更好的方法将另一个UIView合并到我的

我有一个叫做GraphView的类,它扩展了UIView,基本上画了一个小折线图。在我的UITableView中,我需要在每个部分的顶部有一个这样的图。因此,我尝试在我的一个部分顶部创建一个单独的单元格,然后在该单元格上:

[cell.contentView addSubview:graphView];
[graphView release];
但当我向下滚动时,它就像是一个闪烁的图形,它显示在UITableView的随机点上。有人有想法或见解吗?是否有更好的方法将另一个UIView合并到我的UITableView中每个部分的顶部

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

    UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
    }
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont systemFontOfSize:12];
    cell.detailTextLabel.font = [UIFont systemFontOfSize:12];


    NSString *str1, *str2;
    if(indexPath.section == 0) {
        if(indexPath.row == 0) {

            str1 = @"";
            str2 = @"";

            S7GraphView *graphView = [[S7GraphView alloc] initWithFrame:CGRectMake(10,0,310,100)];
            graphView.dataSource = self;

            NSNumberFormatter *numberFormatter = [NSNumberFormatter new];
            [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
            [numberFormatter setMinimumFractionDigits:0];
            [numberFormatter setMaximumFractionDigits:0];

            graphView.yValuesFormatter = numberFormatter;

            NSDateFormatter *dateFormatter = [NSDateFormatter new];
            [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
            [dateFormatter setDateStyle:NSDateFormatterShortStyle];

            graphView.xValuesFormatter = dateFormatter;

            [dateFormatter release];        
            [numberFormatter release];

            graphView.backgroundColor = [UIColor whiteColor];

            graphView.drawAxisX = NO;
            graphView.drawAxisY = YES;
            graphView.drawGridX = NO;
            graphView.drawGridY = YES;

            graphView.xValuesColor = [UIColor blackColor];
            graphView.yValuesColor = [UIColor blackColor];

            graphView.gridXColor = [UIColor blackColor];
            graphView.gridYColor = [UIColor blackColor];

            graphView.drawInfo = NO;
            graphView.info = @"Load";
            graphView.infoColor = [UIColor whiteColor];


            //When you need to update the data, make this call:

            //[graphView reloadData];

            //S7GraphView *graphView = [[S7GraphView alloc] initWithFrame:CGRectMake(10,0,320,300)];
            //self.graphView.dataSource = self;
            [cell.contentView addSubview:graphView];
            [graphView release];
        }

正如我所想,这是一个单元重用问题:

每次执行
tableView:cellforrowatinexpath:
get时,您都会添加另一个GraphView实例。与单元重用相结合,单元对象被重新分配到其他IndExpath,这会带来很大的麻烦

如果(单元格==nil),则应仅在
内添加子视图


你必须单独跟踪或记录你的图形视图。要么将它们添加到以indexPaths为键的NSDictionary中,要么将UITableViewCell子类化。

一个表视图的工作原理可能与最初的预期略有不同。基本上,只有您看到的单元才实际加载到内存中。如果你仔细想想,这是有道理的——如果你的表中有10000个项目,全部加载到内存中,那么你的应用程序就会耗尽内存并很快崩溃

滚动时,将实时创建单元格。令人困惑的是:你的单元格不是从头开始创建的,而iOS只是将刚刚离开屏幕的单元格发送出去

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
再说一遍。因此,当您向下滚动时,在顶部单元格中添加的子视图将不会被删除。简短回答:确保在上面的函数中删除/重置子视图,这样您将“重置”表视图中进一步重用的所有已用单元格

iOS为什么这样做?效率-基本上,创建tableview单元格非常昂贵。查找宽度、颜色、绘制形状…+更多需要大量cpu电源和时间。每次重复使用单元比从头开始要有效得多

因此,在单元格创建函数中只重置单元格的必要字段。这样,您可以平滑快速地滚动,但在重新使用单元格之前,单元格的视图/属性将被重置

一开始很困惑?是的。但肯定是更好的方法。

好的,像这样:

static NSString *CellIdentifier = @"Cell";   

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) 
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
    }

//now remove any subview a reused cell might have:   
[cell.contentView.view removeFromSuperview];   
//and in part of the method, you'll need to create the subview if the cell is in the top row.

if (indexPath.row == 0)
{
    [cell.contentView.view addSubview:graphView.view];
}
在您的情况下,它可能会略有不同,因为它是图形视图而不是UIView。但这绝对是它应该是什么样子的基础


希望有帮助

我已经解决了使用标签的问题:

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
    }
    else{
      [[cell.contentView viewWithTag:500] removeFromSuperview];
    }

    ...

    graphView.tag = 500;
    [cell.contentView addSubview:graphView];

   }

可能重复的@Robert:当人们试图回答你的问题时,请不要重复你的问题。这听起来像是一个细胞重用问题。请发布您的
tableView:cellForRowAtIndexPath:
这不是一个重复的问题。我想出了如何添加UIView。现在我有一个单独的问题…没有重复的细胞。UIView和[cell.contentView addSubview:graphView]仅在indexPath.section==0和indexPath.row==0时调用。我仍然不确定您的意思。因此,在cell.contentView addSubview调用之前添加一个if语句,看看cell==nil吗?关于跟踪图形视图,你是什么意思?非常感谢。你介意解释一下我如何像你说的那样“删除/重置上面函数中的子视图”吗?所以基本上我会在CellForRowatineXpath方法之前创建子视图。那么,在该方法内部会有什么呢?在cellForRowAtIndexPath方法内部,在“if(cell==nil)”部分之后,按如下方式重置子视图:[cell.contentView.view removeFromSuperview];但是,如果单元实际位于行的顶部,则还需要创建子视图。因此,稍后,在同一个cellForRowAtIndexPath方法中,有一些代码可以执行以下操作:if(indexath.row==0){//创建图形视图并将其添加到此处的单元格内容视图。}所以您是说:if(cell==nil){[cell.contentView removeFromSuperview];}否则{创建视图和[cell.contentView addSubview:graphView.view];}?这不管用,不是我的意思。我会把它写出来作为一个答案,而不是试着把它放在评论里!非常感谢。我用另一种方式使用标签。如果单元格有一个带有该标记的视图,那么我没有将子视图添加到内容视图中。您不应该用大写字母启动
CellIdentifier
变量,而是使用
CellIdentifier