所以,这是我的cellForRowAtIndexPath的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"identifier"]autorelease];
}
NSInteger artistIndex = 1; // 1
NSInteger albumIndex = 3; // 3
NSInteger dateIndex = 6; // 6
NSInteger imageIndex = 8; // 5
// ARTIST
CGRect frame = CGRectMake(59, 11, 244, 13);
UILabel *label = [[UILabel alloc]initWithFrame:frame];
label.font = [UIFont boldSystemFontOfSize:13];
label.textColor = [UIColor blackColor];
label.text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:artistIndex];
[cell addSubview:label];
// ALBUM (more like description...
frame = CGRectMake(60, 30, 244, 11);
label = [[UILabel alloc]initWithFrame:frame];
label.font = [UIFont boldSystemFontOfSize:11];
label.textColor = [UIColor darkGrayColor];
label.text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:albumIndex];
[cell addSubview:label];
// DATE
frame = CGRectMake(59, 49, 244, 10);
label = [[UILabel alloc]initWithFrame:frame];
label.font = [UIFont fontWithName:@"Helvetica" size:10.0];
label.textColor = [UIColor darkGrayColor];
label.textAlignment = UITextAlignmentRight;
label.text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:dateIndex];
[cell addSubview:label];
// IMAGE
UIImageView *imageView = [[UIImageView alloc]init];
imageView.image = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:imageIndex];
imageView.frame = CGRectMake(8,9,44,44);
[imageView.layer setMasksToBounds:YES];
[imageView.layer setCornerRadius:3.0];
[[cell contentView] addSubview:imageView];
[imageView release];
[label release];
return cell;
}
为了解释发生了什么,基本上它只是点击一个存储除了索引8(存储UIImage)之外的所有内容的字符串的数组。
我没有设置自动释放的变量(主要是因为我真的不明白自动释放还是大声笑)
无论如何,当滚动应用程序时,它会逐渐减慢(主要是因为UIImage,但也部分是因为标签和框架)。
有没有更好地管理我的记忆?还有,有更好的编码方式吗?我正在考虑制作一个UITableViewCells数组,并通过cellForRowAtIndexPath访问它们。
所以我很想得到一些建议,谢谢你们。
答案 0 :(得分:12)
你在那里泄露了很多标签。每次分配/初始化新标签时都需要释放它。目前,您通过为其分配新标签对象而不释放旧标签对象,多次重复使用相同的标签变量。
不要将[标签发布]放在最后,在每个[cell addSubview:label]之后放置[标签发布];
您的下一个问题是您误解了表格单元格的回收方式。 UITableCell对象在表中反复使用,这就是为什么这样做的原因:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"identifier"]autorelease];
}
这基本上是说"检查是否有可用的单元格,如果没有创建新的单元格"。重新使用单元格时,它会保留您添加的所有旧内容。因此,当您将这些标签和图像视图添加到单元格时,它们会在下次使用时保留在该单元格中,并在下次使用时保留在该单元格中。
但是因为每次重复使用单元格时都会再次添加标签,所以它会构建多个标签副本,因此第二次显示单元格时标签的数量是标签的两倍,下一次是标签的3倍很多,等等。您无法看到重复项,因为它们位于完全相同的位置,但它们会耗尽内存并降低您的桌面速度。
您需要移动代码,将新视图附加到" if(cell == nil){...}"声明,因此标签只在创建单元格时添加一次。
当然这意味着每个单元格都有相同的文本和图像,这是您不想要的,因此您需要拆分设置文本和图像的逻辑,并将其放在if语句之后。这样您只需创建一次标签,但每次在不同的表格行中显示时都会设置文本。这有点棘手,因为您不再拥有对标签的引用,但您可以通过在标签上设置唯一标记来实现,这样您就可以再次找到它们。
这是一个清理过的版本,并删除了所有泄漏:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];
NSInteger artistTag = 1;
NSInteger albumTag = 2;
NSInteger dateTag = 3;
NSInteger imageTag = 4;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"identifier"]autorelease];
// ARTIST
CGRect frame = CGRectMake(59, 11, 244, 13);
UILabel *label = [[UILabel alloc]initWithFrame:frame];
label.font = [UIFont boldSystemFontOfSize:13];
label.textColor = [UIColor blackColor];
label.tag = artistTag;
[cell addSubview:label];
[label release];
// ALBUM (more like description...
frame = CGRectMake(60, 30, 244, 11);
label = [[UILabel alloc]initWithFrame:frame];
label.font = [UIFont boldSystemFontOfSize:11];
label.textColor = [UIColor darkGrayColor];
label.tag = albumTag;
[cell addSubview:label];
[label release];
// DATE
frame = CGRectMake(59, 49, 244, 10);
label = [[UILabel alloc]initWithFrame:frame];
label.font = [UIFont fontWithName:@"Helvetica" size:10.0];
label.textColor = [UIColor darkGrayColor];
label.textAlignment = UITextAlignmentRight;
label.tag = dateTag;
[cell addSubview:label];
[label release];
// IMAGE
UIImageView *imageView = [[UIImageView alloc]init];
imageView.frame = CGRectMake(8,9,44,44);
imageView.tag = imageTag;
[imageView.layer setMasksToBounds:YES];
[imageView.layer setCornerRadius:3.0];
[[cell contentView] addSubview:imageView];
[imageView release];
}
NSInteger artistIndex = 1; // 1
NSInteger albumIndex = 3; // 3
NSInteger dateIndex = 6; // 6
NSInteger imageIndex = 8; // 5
((UILabel *)[cell viewWithTag:artistTag]).text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:artistIndex];
((UILabel *)[cell viewWithTag:albumTag]).text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:albumIndex];
((UILabel *)[cell viewWithTag:dateTag]).text = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:dateIndex];
((UIImageView *)[cell viewWithTag:imageTag]).image = [[musicList.list objectAtIndex:indexPath.row] objectAtIndex:imageIndex];
return cell;
}
答案 1 :(得分:5)
为了提高内存使用效率并获得更流畅的滚动性能,您应该创建一个自定义UITableViewCell子类,其中包含一个自定义UIView作为UITableViewCell的contentView的子视图。您应该使用 -drawRect:在此自定义视图上绘图。拥有一个大视图层次结构是非常占用大量内存的,而不是只有一个视图直接在其上绘制所有内容。
Apple的TableViewSuite示例实际上包含了这种直接绘图方法的示例。在这里下载项目:
http://developer.apple.com/library/ios/#samplecode/TableViewSuite/Introduction/Intro.html
查看第五个示例,了解如何在您自己的项目中实现高性能,低内存自定义tableview单元格绘制。
答案 2 :(得分:0)
为什么不在IB和子类UITableViewCell中构建你的单元来根据你的需要定制它(3个UILabels和一个UIImageView)?我有复杂的tableview单元设计,这个系统适合我。使代码更清晰,更易于管理。如果你需要一个有效的例子,我可以发给你。
答案 3 :(得分:0)
尝试设置静态字符串并在以下方法中使用:
static NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier]autorelease];
答案 4 :(得分:0)
总之,泄漏原因是addSubview的额外引用。 所以确保addSubview一次或删除它之后再添加新的。