滚动表格视图时应用程序崩溃

Posted

技术标签:

【中文标题】滚动表格视图时应用程序崩溃【英文标题】:App crashing when scrolling table view 【发布时间】:2011-06-23 19:47:47 【问题描述】:

在我的应用程序中,我有一个表格视图在一行中显示图像视图,4 个图像视图。我的问题是,在使用一些数据加载表格视图之后,如果我尝试滚动表格视图,那么我的应用程序就会崩溃。在使用断点时,我发现再次调用索引路径方法中的行单元格,并且我的数组尝试再次重新加载数据。请帮助,因为它现在让我头疼,我在这里发布我的代码:--

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

    UITableViewCell *cell = nil;



    static NSString *AutoCompleteRowIdentifier = @"AutoCompleteRowIdentifier";

    cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];

    if (cell == nil) 

        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier] autorelease];


        UIImageView * imageView1 = [[[UIImageView alloc] initWithFrame:CGRectMake(25, 4, 70, 80)] autorelease];

        UIImageView * imageView2 = [[[UIImageView alloc] initWithFrame:CGRectMake(115,4,70, 80)] autorelease];

        UIImageView * imageView3 = [[[UIImageView alloc] initWithFrame:CGRectMake(205,4, 70, 80)] autorelease];

        UIImageView * imageView4 = [[[UIImageView alloc] initWithFrame:CGRectMake(295,4, 70, 80)] autorelease];

        UIImageView * imageView5 = [[[UIImageView alloc] initWithFrame:CGRectMake(25, 4, 70, 80)] autorelease];

        UIImageView * imageView6 = [[[UIImageView alloc] initWithFrame:CGRectMake(115,4,70, 80)] autorelease];

        UIImageView * imageView7 = [[[UIImageView alloc] initWithFrame:CGRectMake(205,4, 70, 80)] autorelease];

        UIImageView * imageView8 = [[[UIImageView alloc] initWithFrame:CGRectMake(295,4, 70, 80)] autorelease];

        UIImageView * imageView9 = [[[UIImageView alloc] initWithFrame:CGRectMake(25, 4, 70, 80)] autorelease];

        UIImageView * imageView10 = [[[UIImageView alloc] initWithFrame:CGRectMake(115,4,70, 80)] autorelease];

        UIImageView * imageView11 = [[[UIImageView alloc] initWithFrame:CGRectMake(205,4, 70, 80)] autorelease];

        UIImageView * imageView12 = [[[UIImageView alloc] initWithFrame:CGRectMake(295,4, 70, 80)] autorelease];



        imageView1.tag=1;
        imageView2.tag=2;
        imageView3.tag=3;
        imageView4.tag=4;
        imageView5.tag=5;
        imageView6.tag=6;
        imageView7.tag=7;
        imageView8.tag=8;
        imageView9.tag=9;
        imageView10.tag=10;
        imageView11.tag=11;
        imageView12.tag=12;



        if ([sentence count]>0) 

            [imageViewArray insertObject:imageView1 atIndex:0];

            [cell.contentView addSubview:imageView1];

        

        if ([sentence count]>1) 

            [imageViewArray insertObject:imageView2 atIndex:1];

            [cell.contentView addSubview:imageView2];

        

        if ([sentence count]>2) 

            [imageViewArray insertObject:imageView3 atIndex:2];

            [cell.contentView addSubview:imageView3];
        

        if ([sentence count]>3) 

            [imageViewArray insertObject:imageView4 atIndex:3];

            [cell.contentView addSubview:imageView4];
        
        if ([sentence count]>4) 
            [imageViewArray insertObject:imageView5 atIndex:4];

            [cell.contentView addSubview:imageView5];
        
        if ([sentence count]>5) 
            [imageViewArray insertObject:imageView6 atIndex:5];

            [cell.contentView addSubview:imageView6];
        
        if ([sentence count]>6) 
            [imageViewArray insertObject:imageView7 atIndex:6];

            [cell.contentView addSubview:imageView7];
        
        if ([sentence count]>7) 
            [imageViewArray insertObject:imageView8 atIndex:7];

            [cell.contentView addSubview:imageView8];
        
        if ([sentence count]>8) 
            [imageViewArray insertObject:imageView9 atIndex:8];

            [cell.contentView addSubview:imageView9];
        
        if ([sentence count]>9) 
            [imageViewArray insertObject:imageView10 atIndex:9];

            [cell.contentView addSubview:imageView10];
        
        if ([sentence count]>10) 
            [imageViewArray insertObject:imageView11 atIndex:10];

            [cell.contentView addSubview:imageView11];
        
        if ([sentence count]>11 || ([sentence count]==12)) 
            [imageViewArray insertObject:imageView12 atIndex:11];

            [cell.contentView addSubview:imageView12];
        

    

        if ([sentence count]!=0) 



    int photosInRow;

        if ( (indexPath.row < 

[tableView numberOfRowsInSection:indexPath.section] - 1) || ([sentence count] % 4 == 0) ) 

        photosInRow = 4;

     else 

        photosInRow = [sentence count] % 4;
    


    for ( int i = 1; i <=photosInRow ; i++ )

        imageView = (UIImageView *)[cell.contentView viewWithTag:j];

        [self setImage1:imageView];
        

    
        return cell;



【问题讨论】:

经过 72 个问题,我想一个人会弄清楚如何正确格式化代码。 【参考方案1】:

我相信这里最大的问题是 imageViews 的内存泄漏。每个单元格创建 12 个 imageView,没有一个被释放。看来你应该只创建你需要的图像视图(为了速度),并正确释放它们(为了内存管理)。

开始重写此代码的一种方法如下:

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

    static NSString *AutoCompleteRowIdentifier = @"AutoCompleteRowIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];

    if (!cell) 

        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier] autorelease];

        for (int i=0; i <= [sentence count]; ++i) 
            UIImageView * imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(25+90*(i%4), 4, 70, 80)] autorelease];
            imageView.tag = i+1;
            [cell.contentView addSubview:imageView];
            [imageView release];
        
    
    return cell;

我不明白你为什么要反复设置imageViewArrayimageView1。另外,这一行:

   imageView = (UIImageView *)[cell.contentView viewWithTag:j];

没有意义,因为 j 没有定义。

【讨论】:

非常感谢,从现在开始我会处理代码格式 @Christina:它所以更容易阅读。另外,不要害怕 for 循环......它们使您的代码更易于阅读和编辑,因此从长远来看应该可以为您节省大量时间。 但是当我滚动表格视图时我的应用程序仍然崩溃【参考方案2】:

在使用断点时,我发现索引路径方法的行单元格被再次调用,我的数组再次尝试重新加载数据。

没错。如果你不明白这一点,你就不会明白表格视图是如何工作的。单元是按需创建并重复使用的;当用户滚动时,相同的单元格可能会一次又一次地重复用于表格的不同行。这意味着您必须事先准备所有数据,然后简单地按需为请求的任何部分/行获取数据。

换句话说,MVC:模型-视图-控制器。你的模型就是你的数据。 tableView:cellForRowAtIndexPath: 是视图;在此期间您不得修改模型,因为调用它的时间和频率完全取决于视图的需要。

另一件事是您不应该制作单独的图像视图数组。图像视图是视图。如果您想存储某物的列表,请存储图像名称或某物的列表。

【讨论】:

以上是关于滚动表格视图时应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

滚动表格视图时,iOS 应用程序随机崩溃,不确定如何处理引发的错误

滚动时 UITableView 崩溃

滚动表视图然后突然单击搜索栏会导致应用程序崩溃?

UITableView 在快速滚动时崩溃

未知异常和崩溃

滚动表格视图后点击选择行时如何修复崩溃?