简体   繁体   中英

Memory Leak UITableView

SOLUTION

Just read the answer of @Kjuly

Thanks alot

QUESTION

I used tableView with sections, each section has 4 rows, the first row it must show image from website which I used HJCache class to cache the image and avoid leaking/memory issues.

now, this code it works well and while I am scrolling fast it doesn't leak or make memory issue

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //UITableViewCell *cell=nil;

    if (indexPath.row == 0) {
    static NSString *CellIdentifier = @"Cell";
    HJManagedImageV* mi;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];


        mi = [[HJManagedImageV alloc] initWithFrame:CGRectMake(0,0,cell.frame.size.width, 310)];
        mi.tag = 999;

        [cell addSubview:mi];

    } else {
        mi = (HJManagedImageV*)[cell viewWithTag:999];
        [mi clear];

    }



    if (indexPath.row == 0) {

        mi.image = [UIImage imageNamed:@"placeholder"];

    mi.url = [NSURL URLWithString:[pictures objectAtIndex:indexPath.section]];

    [objMan manage:mi];
        UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(likeTappedDouble:)];
        tapped.numberOfTapsRequired = 2;

        [mi setUserInteractionEnabled:YES];
        [mi addGestureRecognizer:tapped];



    }

        return cell;

    }
}

But when I try to configure other rows it leaked and while scrolling the application make memory issue and be very slowly.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //UITableViewCell *cell=nil;

    if (indexPath.row == 0) {
    static NSString *CellIdentifier = @"Cell";
    HJManagedImageV* mi;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];


        mi = [[HJManagedImageV alloc] initWithFrame:CGRectMake(0,0,cell.frame.size.width, 310)];
        mi.tag = 999;

        [cell addSubview:mi];

    } else {
        mi = (HJManagedImageV*)[cell viewWithTag:999];
        [mi clear];

    }



    if (indexPath.row == 0) {

        mi.image = [UIImage imageNamed:@"placeholder"];

    mi.url = [NSURL URLWithString:[pictures objectAtIndex:indexPath.section]];

    [objMan manage:mi];


        UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(likeTappedDouble:)];
        tapped.numberOfTapsRequired = 2;

        [mi setUserInteractionEnabled:YES];
        [mi addGestureRecognizer:tapped];



    }

        return cell;

    }



    static NSString *CellIdentifier = @"CellS";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];



    if (indexPath.row == 1) {
        // configure row 1
    }
        if (indexPath.row == 2) {
            // configure row 2
        }

    // etc for the others ..

    return cell;
}

Where is the problem, Thanks..

UPDATE

This code doesn't work well, it add the subview in other row while scrolling

 static NSString *CellIdentifier = @"CellS";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

        if (indexPath.row == 1) {
            UIImage* likesimage = [UIImage imageNamed:@"likespic"];
            CGRect frameimg = CGRectMake(7, 5, likesimage.size.width, likesimage.size.height);
            likesbutton = [[UIButton alloc] initWithFrame:frameimg];
            [likesbutton setBackgroundImage:likesimage forState:UIControlStateNormal];
            likesbutton.backgroundColor = [UIColor clearColor];
            [cell addSubview:likesbutton];

            label3 = [[UILabel alloc] initWithFrame:CGRectMake(20, 2, 100, 20)];
            label3.textColor = [UIColor colorWithRed:61.0/255.0 green:113.0/255.0 blue:154.0/255.0 alpha:1.0];
            label3.backgroundColor = [UIColor clearColor];
            label3.font = [UIFont fontWithName:@"Helvetica-Bold" size:12];
            label3.adjustsFontSizeToFitWidth = YES;

            [cell addSubview:label3];



        }

    }

For your other cells, you need to reuse the cell either:

static NSString *CellIdentifier = @"CellS";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
  cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

EDIT for Updated Question:

You need to know how "cell reusing" works. As for your updated code, it said only row 1 needs the subviews like image, right? So you need add it outside of the if (cell == nil){} snippet, like the code below:

static NSString *CellIdentifier = @"CellS";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
  cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
  cell.selectionStyle = UITableViewCellSelectionStyleNone;
}

if (indexPath.row == 1) {
  UIImage* likesimage = [UIImage imageNamed:@"likespic"];
  CGRect frameimg = CGRectMake(7, 5, likesimage.size.width, likesimage.size.height);
  likesbutton = [[UIButton alloc] initWithFrame:frameimg];
  [likesbutton setBackgroundImage:likesimage forState:UIControlStateNormal];
  likesbutton.backgroundColor = [UIColor clearColor];
  [cell addSubview:likesbutton];

  label3 = [[UILabel alloc] initWithFrame:CGRectMake(20, 2, 100, 20)];
  label3.textColor = [UIColor colorWithRed:61.0/255.0 green:113.0/255.0 blue:154.0/255.0 alpha:1.0];
  label3.backgroundColor = [UIColor clearColor];
  label3.font = [UIFont fontWithName:@"Helvetica-Bold" size:12];
  label3.adjustsFontSizeToFitWidth = YES;

  [cell addSubview:label3];
}

Note : It's better to create a new cell instance like what you did for row 0, cause it's only need to be created once.

try this ...

man you are doing 2 mistakes here

  1. not checking for dequeued cells.

  2. after allocating the cell , you are not releasing it's memory.

i suggest this code for you .

- (UITableViewCell *)tableView:(UITableView *)tableView 
                             cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
       static NSString *CellIdentifier = @"cellID";
       UITableViewCell *cell = [tableView    
                              dequeueReusableCellWithIdentifier:CellIdentifier];
       if (cell == nil)
       {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                          reuseIdentifier:CellIdentifier] autorelease];
       }
}

don't forget to autorelease cells .

remove all add subviews, then add new subviews

NSArray *subviews = [[NSArray alloc] initWithArray:cell.contentView.subviews];
for (UIView *subview in subviews) {
    [subview removeFromSuperview];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM