Ios 将图像加载到UITableView中的自定义单元格时内存泄漏

Ios 将图像加载到UITableView中的自定义单元格时内存泄漏,ios,uitableview,memory-leaks,uiimageview,custom-cell,Ios,Uitableview,Memory Leaks,Uiimageview,Custom Cell,在我的iPhone应用程序中,具有自定义单元格的UITableView。其中包含UILabels和UIImageView。但是,当我将图像指定给图像视图时,内存泄漏。这是代码。泄漏在方法CellForRowatineXpath中:我已经提到了泄漏百分比。请检查代码,这里出了什么问题?请帮忙 // UIMenuItemCell.h @class UIMenuitemImage; @interface UIMenuItemCell :

在我的iPhone应用程序中,具有自定义单元格的UITableView。其中包含UILabels和UIImageView。但是,当我将图像指定给图像视图时,内存泄漏。这是代码。泄漏在方法CellForRowatineXpath中:我已经提到了泄漏百分比。请检查代码,这里出了什么问题?请帮忙

        //  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
使用:


编辑以回应评论:

释放IVAR的正确方法是dealloc方法。如果它没有被调用,这意味着你的UIMenuItemCells没有被释放。这可能是因为您的实现工作的方式;您正在为表视图中的每一行创建一个可重用的单元格。我认为,如果您将一个单元格标记为可重用,那么直到表视图被释放,它才会被释放

您可以通过查看在释放表视图时是否释放了所有内存来测试这一点(如果在应用程序中发生这种情况)。这意味着您实际上没有泄漏,只是您的应用程序使用了大量内存(很可能是不必要的)。您还可以测试当您将已经创建的行重新滚动到屏幕上时,内存是否会增加,因为在这种情况下,我认为您将重用单元格,因此内存不应该增加。 您还可以尝试使用nil作为单元格标识符初始化表视图单元格,以便在滚动到屏幕外时释放这些单元格

不过,您可能应该尝试重新编写代码,以便真正重用单元格。否则,滚动很可能会变得非常不稳定。

在您的方法中

- (UIMenuItemCell *) getCellContentView:(NSString *)cellIdentifier
使用:


编辑以回应评论:

释放IVAR的正确方法是dealloc方法。如果它没有被调用,这意味着你的UIMenuItemCells没有被释放。这可能是因为您的实现工作的方式;您正在为表视图中的每一行创建一个可重用的单元格。我认为,如果您将一个单元格标记为可重用,那么直到表视图被释放,它才会被释放

您可以通过查看在释放表视图时是否释放了所有内存来测试这一点(如果在应用程序中发生这种情况)。这意味着您实际上没有泄漏,只是您的应用程序使用了大量内存(很可能是不必要的)。您还可以测试当您将已经创建的行重新滚动到屏幕上时,内存是否会增加,因为在这种情况下,我认为您将重用单元格,因此内存不应该增加。 您还可以尝试使用nil作为单元格标识符初始化表视图单元格,以便在滚动到屏幕外时释放这些单元格


不过,您可能应该尝试重新编写代码,以便真正重用单元格。否则,滚动很可能会变得非常不稳定。

我遇到了类似的问题,并最终解决了它

因为你的表格单元以后会被重用


因此,在将子视图添加到单元格之前,只需调用removeFromSuperview。

我遇到了类似的问题,并最终解决了它

因为你的表格单元以后会被重用


因此,在将子视图添加到单元格之前,只需调用removeFromSuperview。

您永远不会释放单元格,这是导致泄漏的原因。从getCellContentView方法返回单元格时,对其调用autorelease。我还想指出,您的代码组织方式违反了回收单元的目的。
getCellContentView
方法到底做了什么?我尝试了Darren所说的自动释放,但仍然存在漏洞。作为这个imageview和label的一部分,我还在这个单元格中使用progressview。即使导航到另一个视图,我也需要保持进度。@Malloc这是为了设置自定义单元格的对象。您永远不会释放单元格,这是导致泄漏的原因。从getCellContentView方法返回单元格时,对其调用autorelease。我还想指出,您的代码组织方式违反了回收单元的目的。
getCellContentView
方法到底做了什么?我尝试了Darren所说的自动释放,但仍然存在漏洞。作为这个imageview和label的一部分,我还在这个单元格中使用progressview。即使导航到另一个视图,我也需要保持进度。@Malloc这是为了设置自定义单元格的对象。@john如果要自动删除单元格,则不再有泄漏。如果您仍然看到一个,那么这意味着您没有发布实际的剪切粘贴代码。如果你不发布你的实际代码,我们无法帮助你。谢谢你的回复,我已经更新了代码,除此之外,我需要保持进度条的进度,即使在一些导航之后。这就是为什么我害怕释放整个细胞。如你所说,我试过自动释放,但没有效果。请检查代码。@John您是否在UIMenuItemCell dealoc方法中释放合成IVAR?没有,但我在UIMenuItemCell.m中添加了-(void)dealoc方法并试图释放IVAR,但该方法未被调用。有没有合适的方法来释放子类中的对象?@john如果你正在自动释放单元格,那么就不会有泄漏。如果您仍然看到一个,那么这意味着您没有发布实际的剪切粘贴代码。如果你不发布你的实际代码,我们无法帮助你。谢谢你的回复,我已经更新了代码,除此之外,我需要保持进度条的进度,即使在一些导航之后。这就是为什么我害怕释放整个细胞。如你所说,我试过自动释放,但没有效果。请检查代码。@John您是否在UIMenuItemCell dealoc方法中释放合成IVAR?没有,但我在UIMenuItemCell.m中添加了-(void)dealoc方法并试图释放IVAR,但该方法未被调用。有没有合适的方法来释放子类中的对象?