cellForRowAtIndexPath内存pipe理
所以,这是我的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)以外的所有string。
我没有variables设置autorelease(主要是因为我真的不明白自动释放只是大声笑)
无论如何,当滚动应用程序,它会逐步减慢(主要是因为UIImage,但也部分由于标签和框架)。
有没有办法更好地pipe理我的记忆? 另外,有没有更好的方式来编码? 我正在考虑制作一个UITableViewCells数组,然后通过cellForRowAtIndexPath访问这些数组。
所以我会喜欢一些build议,谢谢你们。
你在这里泄漏了很多标签。 每次你分配/初始化一个新的标签,你需要释放它。 目前,您正在重新使用相同的标签variables,方法是分配一个新的标签对象而不释放旧标签对象。
在每个[cell addSubview:label]之后放置[label release],而不是将[label release]放在最后。
你的下一个问题是你误解了表格单元的回收工作。 UITableCell对象在表中重复使用,为什么你这样做:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"identifier"]autorelease]; }
这基本上是说“检查是否有可用的单元格,如果不是创build一个新的单元格”。 当一个单元格被重新使用时,它会保留所有添加的旧单元格。 因此,当您将这些标签和图片视图添加到单元格时,它们会在下一次使用时保留在该单元格中,并在下一次使用。
但是由于每次重新使用单元格时都要重新添加标签,因此会生成多个标签副本,因此第二次显示单元格时,标签的数量是标签的两倍,下一次是标签的三倍,等等。 你看不到重复的东西,因为它们在完全相同的地方,但是它们正在使用内存并减慢你的表格的速度。
您需要将添加新视图的代码移动到“if(cell == nil){…}”语句中的单元格中,因此只在创build单元格时添加标签。
当然,这意味着每个单元格都将具有相同的文本和图像,这是您不需要的,所以您需要将设置文本和图像的逻辑分开,并将其放在if语句之后。 这样,您只能创build一次标签,但每次在不同的表格行中显示文本时都要设置文本。 这有点棘手,因为你没有对标签的引用,但你可以通过在标签上设置独特的标签来做到这一点,所以你可以再次find它们。
这是一个清除了所有泄漏的版本:
- (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; }
为了提高内存使用效率并获得更平滑的滚动性能,您应该创build一个自定义的UITableViewCell子类,它包含一个自定义的UIView作为UITableViewCell的contentView的子视图。 你应该使用-drawRect:绘制这个自定义视图。 拥有一个大的视图层次结构是内存密集型的,而不是只有一个视图直接绘制所有的内容。
Apple的TableViewSuite实例实际上包含了这个直接绘图方法的一个例子。 在这里下载项目:
http://developer.apple.com/library/ios/#samplecode/TableViewSuite/Introduction/Intro.html
查看第五个示例,了解如何在自己的项目中实现高性能,低内存自定义tableview单元绘图。
为什么不build立你的细胞在IB和UITableViewCell的子类,以适应您的需求(3 UILabels和UIImageView)? 我有复杂的桌面单元devise,这个系统对我来说效果很好。 保持代码更清洁,更易于pipe理。 如果你需要一个工作的例子,我可以把它发送给你。
尝试设置一个静态string,并在下面的方法中使用它:
static NSString *identifier = @"identifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier]autorelease];
总之,泄漏原因是addSubview的附加引用。 所以确保addSubview一次或删除它之前添加一个新的。