通过cell.contentView将UIView添加到UITableViewCell

时间:2011-01-02 00:52:00

标签: iphone ios uitableview

我有一个名为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];
        }

4 个答案:

答案 0 :(得分:13)

表视图的工作方式与您最初的预期略有不同。基本上,只有您看到的单元格实际上已加载到内存中。如果您考虑一下,这是有道理的 - 如果您的表中有10,000个项目,全部加载到内存中,您的应用程序将耗尽内存并快速崩溃。

滚动时,您的单元格会实时创建。令人困惑的部分:您的单元格不是从头开始创建的,而是iOS只需要一个刚刚离开屏幕并通过它发送的单元格

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

一次。因此,当您滚动时,当该单元格被进一步向下重用时,您添加到顶部单元格的子视图将不会被删除。简短回答:确保在上面的函数中删除/重置子视图,这样你就可以“重置”在表视图中进一步重用的任何用过的单元格。

为什么iOS会这样做?效率 - 基本上,创建tableview单元非常昂贵。找到宽度,颜色,绘制形状... +更多需要大量的CPU功率和时间。每次重复使用细胞效率要高得多,而不是从头开始。

因此,只需在单元格创建功能中重置单元格的必要字段。这样,您将获得平滑且快速的滚动,但在重复使用单元格之前,将重置单元格的视图/属性。

一开始很困惑?对。但绝对是更好的方法。

答案 1 :(得分:10)

我已经解决了使用标签:

- (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];

   }

答案 2 :(得分:4)

好像这样:

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,在您的情况下可能略有不同。但这绝对是它应该是什么样子的基础。

希望有所帮助!

答案 3 :(得分:3)

正如我所想,这是一个细胞重用问题:

每次执行tableView:cellForRowAtIndexPath:时,都会添加另一个GraphView实例。结合单元重用,将单元对象重新分配给其他索引路径,这会带来很大的麻烦。

您应该只在if (cell == nil)内添加子视图。

您必须单独跟踪或使用GraphView。通过将indexPaths作为键添加到NSDictionary,或者通过子类化UITableViewCell来添加它们。