[英]Memory leak when loading image to custom cell in UITableView
在我的 iPhone 應用程序中,有一個帶有自定義單元格的 UITableView。 其中包含 UILabels 和 UIImageViews。 但是當我將圖像分配給圖像視圖時,我得到了 memory 泄漏。 這是代碼。 泄漏在方法 cellForRowAtIndexPath 中:我已經提到了泄漏百分比。 請檢查代碼,這里出了什么問題? 請幫忙。
// UIMenuItemCell.h
@class UIMenuitemImage;
@interface UIMenuItemCell : UITableViewCell{
UILabel *cellItemName;
UIImageView *cellitemImage;
}
@property (nonatomic, retain) UILabel *cellItemName;
@property (nonatomic, retain) UIImageView *cellitemImage;
// UIMenuItemCell.m
#import "UIMenuItemCell.h"
@implementation UIMenuItemCell
@synthesize cellItemName, cellitemImage, cellItemButton, cellItemProgress;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
// cellitemImage = [[UIMenuitemImage alloc]init];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
// MenuScreenVC.m
- (UIMenuItemCell *) getCellContentView:(NSString *)cellIdentifier {
CGRect CellFrame = CGRectMake(0, 0, 150, 60);
CGRect Label1Frame = CGRectMake(20, 23, 98, 30);
CGRect imgFrame = CGRectMake(20, 48, 110, 123);
CGRect btnFrame = CGRectMake(25, 136, 100, 30);
CGRect progressFrame = CGRectMake(25, 140, 100, 21);
UILabel *lblTemp;
UIImageView *itemImg;
UIButton *itemBtn;
UIProgressView *itemProgView;
UIMenuItemCell *cell = [[[UIMenuItemCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
cell.frame = CellFrame;
//Initialize Label with tag 1.
lblTemp = [[UILabel alloc] initWithFrame:Label1Frame];
lblTemp.tag = 1;
lblTemp.textColor=[UIColor colorWithRed:139.0f/255.0f green:69.0f/255.0f blue:19.0f/255.0f alpha:1.0f];
lblTemp.textAlignment = UITextAlignmentCenter;
lblTemp.backgroundColor = [UIColor clearColor];
lblTemp.font = [UIFont systemFontOfSize:13.0];
[cell.contentView addSubview:lblTemp];
[lblTemp release];
//Initialize ImageView
itemImg = [[UIImageView alloc]initWithFrame:imgFrame];
itemImg.tag = 2;
[cell.contentView addSubview:itemImg];
[itemImg release];
//Initialize Button
itemBtn = [[UIButton alloc]initWithFrame:btnFrame];
itemBtn.frame = btnFrame;
itemBtn.tag = 3;
itemBtn.titleLabel.textColor = [UIColor blueColor];
itemBtn.titleLabel.font = [UIFont systemFontOfSize:9.0];
[cell.contentView addSubview:itemBtn];
[itemBtn release];
//Initialize ProgressView
itemProgView = [[CustomProgressView alloc]initWithFrame:progressFrame];
itemProgView.tag = 4;
//[cell.contentView addSubview:itemProgView];
[itemProgView release];
return cell;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d", indexPath.row];
UIMenuItemCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [self getCellContentView:CellIdentifier];
cell.transform = CGAffineTransformMakeRotation(M_PI_2);
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.cellItemName = (UILabel *)[cell viewWithTag:1];
cell.cellitemImage = (UIImageView *)[cell viewWithTag:2];
cell.cellItemButton = (UIButton *)[cell viewWithTag:3];
cell.cellItemProgress = (UIProgressView *)[cell viewWithTag:4];
DataBaseClass *itemObj = [appDelegate.itemArray objectAtIndex:indexPath.row];
__autoreleasing NSString *imageLocalFilePath = nil;
if ([[tempitemStatusArray objectAtIndex:indexPath.row] isEqualToString:@"NotAvailable"]) {
cell.cellItemProgress.hidden = YES;
cell.cellItemButton.hidden = NO;
imageLocalFilePath = [NSString stringWithFormat:@"%@",[tempItemLocalNotAvailPath objectAtIndex:indexPath.row]];
NSString *date = [self changeDateFormat:itemObj.itemReleaseDate];
[cell.cellItemButton setTitle:date forState:UIControlStateNormal];
cell.cellItemButton.userInteractionEnabled = NO;
cell.userInteractionEnabled = NO;
[cell.cellItemButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"not_available_bttn_bck_img"] forState:UIControlStateNormal];
}else if ([[tempitemStatusArray objectAtIndex:indexPath.row] isEqualToString:@"Available"]){
cell.cellItemButton.userInteractionEnabled = YES;
cell.userInteractionEnabled = YES;
cell.cellItemProgress.hidden = YES;
[cell.cellItemButton setTitle:@"" forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"available_bttn_img_normal"] forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"available_bttn_img_pressed"] forState:UIControlStateHighlighted];
[cell.cellItemButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[cell.cellItemButton addTarget:self action:@selector(confirmationAlert:) forControlEvents:UIControlEventTouchUpInside];
imageLocalFilePath = [NSString stringWithFormat:@"%@",[tempItemLocalAvailPath objectAtIndex:indexPath.row]];
}else if ([[tempitemStatusArray objectAtIndex:indexPath.row] isEqualToString:@"Active"]) {
cell.cellItemButton.userInteractionEnabled = YES;
cell.userInteractionEnabled = YES;
cell.cellItemProgress.hidden = YES;
[cell.cellItemButton setTitle:@"" forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"active_bttn_img_normal"] forState:UIControlStateNormal];
[cell.cellItemButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[cell.cellItemButton addTarget:self action:@selector(alert) forControlEvents:UIControlEventTouchUpInside];
imageLocalFilePath = [NSString stringWithFormat:@"%@",[tempItemLocalAvailPath objectAtIndex:indexPath.row]];
}else if([[tempitemStatusArray objectAtIndex:indexPath.row] isEqualToString:@"Downloading"]) {
imageLocalFilePath = [NSString stringWithFormat:@"%@",[tempItemLocalAvailPath objectAtIndex:indexPath.row]];
[cell.contentView addSubview:myprogressView];
cell.cellItemButton.hidden = YES;
}
if ([imageLocalFilePath isEqualToString:@""]) {
[cell.cellitemImage setImage:[UIImage imageNamed:@"item01.png"]];
}else {
[cell.cellitemImage setImage:[UIImage imageWithContentsOfFile:imageLocalFilePath]];
}
cell.cellItemName.text = [NSString stringWithFormat:@"%@",[tempItemNameArray objectAtIndex:indexPath.row]];
for (UIProgressView *prog in cell.contentView.subviews) {
if ([prog isKindOfClass:[UIProgressView class]]){
if (prog.progress == 1) {
[prog removeFromSuperview];
cell.cellItemButton.hidden = NO;
DataBaseClass *itemObj = [appDelegate.itemArray objectAtIndex:indexPath.row];
NSString *imageLocalFilePath = nil;
if ([[tempitemStatusArray objectAtIndex:indexPath.row] isEqualToString:@"Available"]){
cell.cellItemButton.userInteractionEnabled = YES;
cell.userInteractionEnabled = YES;
cell.cellItemProgress.hidden = YES;
[cell.cellItemButton setTitle:@"" forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"available_bttn_img_normal"] forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"available_bttn_img_pressed"] forState:UIControlStateHighlighted];
[cell.cellItemButton addTarget:self action:@selector(confirmationAlert:) forControlEvents:UIControlEventTouchUpInside];
}else if ([[tempitemStatusArray objectAtIndex:indexPath.row] isEqualToString:@"Active"]) {
cell.cellItemButton.userInteractionEnabled = YES;
cell.userInteractionEnabled = YES;
cell.cellItemProgress.hidden = YES;
[cell.cellItemButton setTitle:@"" forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"active_bttn_img_normal"] forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"active_bttn_img_normal"] forState:UIControlStateHighlighted];
[cell.cellItemButton addTarget:self action:@selector(alert) forControlEvents:UIControlEventTouchUpInside];
}
imageLocalFilePath = [NSString stringWithFormat:@"%@",itemObj.availableLocalIconPath];
if ([imageLocalFilePath isEqualToString:@""]) {
[cell.cellitemImage setImage:[UIImage imageNamed:@"item01.png"]];
}else {
[cell.cellitemImage setImage:[UIImage imageWithContentsOfFile:imageLocalFilePath]];
}
cell.cellItemName.text = [NSString stringWithFormat:@"%@",[tempItemNameArray objectAtIndex:indexPath.row]];
[cell.contentView reloadInputViews];
}
}
}
}else {
for (UIProgressView *prog in cell.contentView.subviews) {
if ([prog isKindOfClass:[UIProgressView class]]){
if (prog.progress == 1) {
[prog removeFromSuperview];
cell.cellItemButton.hidden = NO;
cell.cellItemButton.userInteractionEnabled = YES;
cell.userInteractionEnabled = YES;
[cell.cellItemButton setTitle:@"" forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"active_bttn_img_normal"] forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:@"active_bttn_img_normal"] forState:UIControlStateHighlighted];
[cell.cellItemButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[cell.cellItemButton addTarget:self action:@selector(alert) forControlEvents:UIControlEventTouchUpInside];
}
}
}
}
return cell;
}
用你的方法
- (UIMenuItemCell *) getCellContentView:(NSString *)cellIdentifier
采用:
UIMenuItemCell *cell = [[[UIMenuItemCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
編輯以回應評論:
釋放iVars的正確方法是使用dealloc方法。 如果沒有被調用,則意味着您的UIMenuItemCells沒有被釋放。 這可能是由於您的實現工作的方式所致。 您正在為表格視圖中的每一行創建一個可重復使用的單元格。 我認為,如果將單元格標記為可重復使用,則只有在釋放表視圖后才能釋放該單元格。
您可以通過查看釋放表視圖時是否釋放了所有內存(如果這在您的應用程序中發生)來進行測試。 這意味着您實際上沒有泄漏,只是您的應用程序使用了大量內存(很可能是不必要的)。 您還可以測試一下,當將已經創建的行滾動回到屏幕上時,內存是否增加了,因為在這種情況下,我認為您將重復使用單元格,因此內存不應增加。 您也可以嘗試使用nil作為單元格標識符來初始化表格視圖單元格,以便在滾動到屏幕之外時釋放它們。
不過,您可能應該嘗試重新編寫代碼,以便實際上可以重用單元格。 否則,滾動很有可能會非常不穩定。
我遇到類似的問題,終於解決了。
因為您的表格單元格稍后會被重用,
因此只需在將子視圖添加到單元格之前調用removeFromSuperview。
我在將圖像加載到 imageView 時遇到了 memory 峰值問題。下面的代碼解決了我的問題,
注意:這會降低圖像質量。 在我的例子中,我在較小的圖像視圖中加載圖像。
let resizedImage = image.aspectFittedToHeight(100)
resizedImage.jpegData(compressionQuality: 0.2)
return resizedImage
}
並添加此擴展
extension UIImage {
func aspectFittedToHeight(_ newHeight: CGFloat) -> UIImage {
let scale = newHeight / self.size.height
let newWidth = self.size.width * scale
let newSize = CGSize(width: newWidth, height: newHeight)
let renderer = UIGraphicsImageRenderer(size: newSize)
return renderer.image { _ in
self.draw(in: CGRect(origin: .zero, size: newSize))
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.