UITableView单元内存泄漏

时间:2012-01-30 17:55:46

标签: iphone objective-c ios uitableview memory

我的tableview中有一个漏洞,我正在填充数据。

以下是发生的事情:

我有一个NSMutableArray填充NSDictionaries(联系信息)我每次用户选择一个新的索引字母时从sql数据库加载,该数组都填充了这些联系人的信息。

由于我使用实例变量数组来保存数据,所以在每次交换新数据之前我都会这样:

if (currentConnections != nil) {
    [currentConnections release];
    currentConnections = nil;
}

在重置之前,我会有效地删除旧数据 然而,这就是陌生感开始的地方。在我tableView:cellForRowAtIndexPath:我打这样的电话:

NSString *firstname = [[currentConnections objectAtIndex:indexPath.row]
                       objectForKey:@"firstname"];
UILabel *name = [[UILabel alloc]
                 initWithFrame:CGRectMake(75, 12, 190, 15)];
name.font = [UIFont fontWithName:@"Gotham-Medium.ttf" 
                            size:12];
name.textColor = [UIColor whiteColor];
name.backgroundColor = [UIColor clearColor];
name.text = firstname;

当前连接是字典数组。然后我将UILabel添加为单元格的子视图:

[cell addSubview:name];
[name release];

这样的行为是这样的:

当我按原样运行时(在每次交换之前释放当前连接然后将新数据加载到它),应用程序将因崩溃错误而崩溃。
当我没有发布我添加到单元格的子视图时,应用程序不会崩溃,但我惊恐地看到实时字节继续累积在内存分配工具中,直到我切换联系信息足够我获得内存警告然后崩溃。

在我看来,细胞和子视图中存在一些奇怪的内存所有权问题。我确实将单元格指定为可重用,并在加载每个数据之前将其指定为autorelease。

可能导致此泄漏的任何想法?

编辑:

这是当前的tableView:cellForRowAtIndexPath:

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

static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

cell.accessoryType = UITableViewCellAccessoryNone;

if (cell == nil) {
    NSLog(@"within");
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}

if (!ALOCATED) {


cellName = [[ UILabel alloc ]
                 initWithFrame:CGRectMake(75, 12, 190, 15)
                 ];
cellName.font = [ UIFont 
             fontWithName:@"Gotham-Medium.ttf" 
             size:12 
             ];
cellName.textColor = [ UIColor whiteColor ];
cellName.backgroundColor = [ UIColor clearColor ];

NSString *firstname = [[ currentConnections 
                        objectAtIndex:indexPath.row 
                        ] objectForKey:@"firstname" 
                       ];

firstname = [ firstname stringByAppendingString:@" " ];

NSString *lastname = [[ currentConnections 
                       objectAtIndex:indexPath.row 
                       ] objectForKey:@"lastname" 
                      ];

UIImage *profPic = [[ currentConnections 
                     objectAtIndex:indexPath.row 
                     ] objectForKey:@"profilepicture" 
                    ];
connectionPhoto = [[ UIImageView alloc ] initWithFrame:CGRectMake(10, 8, 56, 56) ];
connectionPhoto.image = profPic;




NSString *fullname = [ firstname stringByAppendingString:lastname ];

cellName.text = fullname;


[ cell addSubview:cellName ];



cellTitle = [[ UILabel alloc ]
                 initWithFrame:CGRectMake(75, 31, 260, 13)
                 ];
cellTitle.font = [ UIFont 
             fontWithName:@"ArialMT" 
             size:10 
             ];
cellTitle.textColor = [ UIColor whiteColor ];
cellTitle.backgroundColor = [ UIColor clearColor ];
cellTitle.text = [[ currentConnections 
                  objectAtIndex:indexPath.row 
                  ] objectForKey:@"title" 
                 ];


[ cell addSubview:cellTitle ];
[ cell addSubview:connectionPhoto ];
[ profPic release ];

    ALOCATED = YES;

} else {



    cellTitle.text = [[ currentConnections 
                       objectAtIndex:indexPath.row 
                       ] objectForKey:@"title" 
                      ];

    connectionPhoto.image = [[ currentConnections 
                                                             objectAtIndex:indexPath.row 
                                                             ] objectForKey:@"profilepicture" 
                             ];


    NSString *firstname = [[ currentConnections 
                            objectAtIndex:indexPath.row 
                            ] objectForKey:@"firstname" 
                           ];

    firstname = [ firstname stringByAppendingString:@" " ];

    NSString *lastname = [[ currentConnections 
                           objectAtIndex:indexPath.row 
                           ] objectForKey:@"lastname" 
                          ];
    NSString *fullname = [ firstname stringByAppendingString:lastname ];

    cellName.text = fullname;

}

return cell;

}

我试图创建一个单元格并重复使用它,每次只更改其子视图的属性。

修改

发生的事情是我正在向细胞对象本身添加子视图,这导致了泄漏,因为这些没有被释放。一旦我开始将视图添加到UITableViewCell成员视图又名cell.contentView,cell.accessoryView等......内存就被释放了。因此,正如下面提到的daniel,要么创建自定义表格单元格并将视图添加到单元格属性,要么将视图添加到成员uitablecellviews而不是单元格本身。以下对我有用:

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

static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

cell.accessoryType = UITableViewCellAccessoryNone;

if (cell == nil) {

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




UILabel *cName = [[ UILabel alloc ]
                 initWithFrame:CGRectMake(105, 10, 190, 15)
                 ];
cName.font = [ UIFont 
             fontWithName:@"Gotham-Medium.ttf" 
             size:12 
             ];
cName.textColor = [ UIColor whiteColor ];
cName.backgroundColor = [ UIColor clearColor ];

NSString *firstname = [[ currentConnections 
                        objectAtIndex:indexPath.row 
                        ] objectForKey:@"firstname" 
                       ];

firstname = [ firstname stringByAppendingString:@" " ];

NSString *lastname = [[ currentConnections 
                       objectAtIndex:indexPath.row 
                       ] objectForKey:@"lastname" 
                      ];

NSString *fullname = [ firstname stringByAppendingString:lastname ];

cName.text = fullname;

[ cell.contentView addSubview:cName ];
[ cName release ];



cell.imageView.image = [[ currentConnections 
                     objectAtIndex:indexPath.row 
                     ] objectForKey:@"profilepicture" 
                    ];



UILabel *cTitle = [[ UILabel alloc ]
                 initWithFrame:CGRectMake(105, 25, 190, 13)
                 ];
cTitle.font = [ UIFont 
             fontWithName:@"ArialMT" 
             size:10 
             ];
cTitle.textColor = [ UIColor whiteColor ];
cTitle.backgroundColor = [ UIColor clearColor ];
cTitle.text = [[ currentConnections 
                  objectAtIndex:indexPath.row 
                  ] objectForKey:@"title" 
                 ];


[ cell.contentView addSubview:cTitle ];
[ cTitle release ];

return cell;

}

2 个答案:

答案 0 :(得分:5)

如果您正在重复使用单元格,并且每次设置单元格时都要向其添加UILabel,那么您可以看到如何分配许多可能导致内存问题的UILabel ...如果要添加标签单元格,你只需要在分配它时执行一次,然后如果单元格作为重用单元格进入,它就已经包含你添加的UILabel,所以你只需要编辑标签文本而不是添加一个新的UILabel ......这只是猜测你发布的内容,更多的代码可能会澄清事情...

问题从您发布的代码中显而易见,您正在泄漏单元实例变量,同时请记住,为表中的每一行调用cellForRowAtIndexPath,因此保留一个实例变量以跟踪某些内容添加到单元格将无法正常工作,var将继续被覆盖,但在您的情况下,您正在泄漏单元格。你正在向UITableViewCell添加单元格,永远不会释放它们,然后在下一次调用cellForRowAtIndexPath时,单元格var会被覆盖而前一个会泄漏,因为你没有办法释放它...你可以通过释放单元格来解决这个问题......

现在你还有一个问题就是使用一个var来跟踪单元格上的标签,请记住,它不是一个被分配用于重用的单元格,它实际上是可以在屏幕上显示的单元格,所以保持跟踪你的问题是一个var不起作用...为了解决这个问题,我将使用label属性为UITableViewCell创建子类,并有一个重置标签文本的方法..

希望这有帮助

答案 1 :(得分:1)

  • 有太多联系人,你无法在同一个数组中加载所有内容?
  • 您可以使用NSMutableArray和方法removeAllObjects。
  • 代码中的
  • [cell addSubview:firstname]; firstname是一个字符串...你不能添加一个NSString作为子视图...我建议创建一个自定义的UITableviewcell,因为单元格被回收,当你使用一个回收的单元格时,在他创建的过程中添加了所有子视图。

    < / LI>