Doug Null
Doug Null

Reputation: 8327

memory leak in cellForRowAtIndexPath with ARC

I get a memory leak in cellForRowAtIndexPath, in a new application, with ARC enabled. The cellForRowAtIndexPath displays just a UILabel. Buf it I add [myUIlabel release]; I get ARC error: "ARC forbids explicit message send of 'release'"

Leak goes away if I remove the UILabel.

I don't want to disable ARC because it makes memory mgmt. easier.

What is the solution?

HERE'S THE CODE...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int   row = indexPath.row;
    float font_size;
    UITextView*  PWR_RX_cover_box;
    int x,y,w,h;

    // Determine which channel:
        int channel = tableView.tag;  // tag=channel, set at init time


    // Prepare to update cell:
        // DOCUMENTATION:  Table View Programming Guide for iOS > Adding subviews to a cell’s content view
        // Give each cell a cell identifier unique to each channel tableView and unique to each row, so that each gets a unique data structure:
        NSString *CellIdentifier = [NSString stringWithFormat:@"%d_%d",channel,indexPath.row];

        //static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
            // if nil: cell(chan, row) has not been created before.  <>nil: cell = data structure previously initialized
        if (cell == nil)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
        }

    // Erase anything previously displayed in the cell, by drawing cell-size big, white label:
        font_size = 10.0;
        // Top, left corner of cell:
            y = 0;  
            x = 0;
        // Entire area of cell:
            h = CHANNEL_ROW_HEIGHT;      // height of cell
            w = channel_tableView_width;   // width of cell
        UILabel* index_label = [[UILabel alloc] initWithFrame: CGRectMake( x,y, w,h)];
        index_label.backgroundColor = [UIColor whiteColor];
        index_label.textAlignment = NSTextAlignmentLeft; // NSTextAlignmentCenter, NSTextAlignmentLeft    NSTextAlignmentRight
        index_label.textColor=[UIColor darkGrayColor];
        index_label.numberOfLines=1;
        index_label.font = [UIFont systemFontOfSize: font_size];
        index_label.text = [NSString stringWithFormat:   @"" ];     
        //index_label.text = [NSString stringWithFormat:   @" *LAST %d *", ++last_ind];     //  normally ""
        [cell.contentView addSubview:index_label ];
        [index_label release];   <<<<<<<<<<<<<<<<<<<   CAUSES ARC COMPILE ERROR
         return cell; 

}

Upvotes: 0

Views: 1828

Answers (2)

hema
hema

Reputation: 199

you are allocating and adding index_label to each cell every time.so it is increasing memory every time. you can create index_label in (cell == nil) block and assign some tag to index_label to access the label each time to update properties of index_label.

solution:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int   row = indexPath.row;
    float font_size;
    UITextView*  PWR_RX_cover_box;
    int x,y,w,h;

    // Determine which channel:
    int channel = tableView.tag;  // tag=channel, set at init time


    // Prepare to update cell:
    // DOCUMENTATION:  Table View Programming Guide for iOS > Adding subviews to a cell’s content view
    // Give each cell a cell identifier unique to each channel tableView and unique to each row, so that each gets a unique data structure:
    NSString *CellIdentifier = [NSString stringWithFormat:@"%d_%d",channel,indexPath.row];

    //static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    // if nil: cell(chan, row) has not been created before.  <>nil: cell = data structure previously initialized
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];

        UILabel* index_label = [[UILabel alloc] initWithFrame: CGRectZero];
        index_label.backgroundColor = [UIColor whiteColor];
        index_label.textAlignment = NSTextAlignmentLeft; // NSTextAlignmentCenter, NSTextAlignmentLeft    NSTextAlignmentRight
        index_label.textColor=[UIColor darkGrayColor];
        index_label.numberOfLines=1;
        index_label.font = [UIFont systemFontOfSize: font_size];
           [cell.contentView addSubview:index_label ];
        index_label.tag=TAG_VALUE;
    }

    // Erase anything previously displayed in the cell, by drawing cell-size big, white label:
    font_size = 10.0;
    // Top, left corner of cell:
    y = 0;
    x = 0;
    // Entire area of cell:
    h = CHANNEL_ROW_HEIGHT;      // height of cell
    w = channel_tableView_width;   // width of cell

    UILabel* index_label=[cell.contentView viewWithTag:TAG_VALUE];
    index_label.text = [NSString stringWithFormat:   @"" ];
    index_label.frame=CGRectMake( x,y, w,h);
    return cell;
}

Upvotes: 2

Robotic Cat
Robotic Cat

Reputation: 5893

You are adding the index_label subview to each cell EVERY TIME you dequeue a cell. You will end up adding the label multiple times and increasing your memory usage; however, this is not a memory leak but a problem in your logic. The memory will be reclaimed when the cell is destroyed.

The solution is simple: Create your UILabel in your cell XIB, Prototype Cell or inside the cell == nil code section. Which one of these options is appropriate depends on how you've written your app; personally I use storyboards with prototype cells.

Upvotes: 2

Related Questions