Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set the table view cell accessory view to retain a previously initialized UIImageView?

Let's say I have a property in my view controller, defined as follows:

@property (nonatomic, retain) UIImageView *checkmarkOffAccessoryView;

I @synthesize this in the implementation, release it in -dealloc and initialize it in -viewDidLoad as follows:

self.checkmarkOffAccessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];

So far so good.

When I use it in my table view delegate as an accessory view for multiple cells, two things happen:

  1. Only one cell's accessory view shows the image
  2. The application UI freezes.

The app doesn't crash, as near as I can tell, the UI simply becomes unresponsive. This is both in the simulator and on the device.

Here is how I use the initialized property with my cell:

- (UITableViewCell *) tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // initialize or dequeue cell...

    if (condition)
        cell.accessoryView = self.checkmarkOffAccessoryView;
    else
        cell.accessoryView = nil;
}

With the aforementioned code, only one cell shows the accessory view and the UI freezes.

If I initialize the UIImageView instance directly in the delegate method I get all condition-satisfying cells showing the accessory view and I do not experience the UI freeze:

- (UITableViewCell *) tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // initialize or dequeue cell...

    if (condition)
        cell.accessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];
    else
        cell.accessoryView = nil;
}

My goal is to initialize as few objects as possible and reuse one UIImageView. I'm curious why the first chunk of code is problematic and what I could do to fix this.

It seems like the cell's accessoryView property should just increment the retain count of self.checkmarkOffAccessoryView but it appears I am missing some detail.

What have I overlooked? Thanks for your advice.

EDIT

I think that:

self.checkmarkOffAccessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];

is the same as:

UIImageView *uncheckedView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]];
self.checkmarkOffAccessoryView = uncheckedView;
[uncheckedView release];

Either way, I experience the same freeze symptom.

like image 271
Alex Reynolds Avatar asked Jul 06 '10 22:07

Alex Reynolds


1 Answers

You cannot add the same view multiple times. The UI handler will go bonkers. To make sure of this, I tried doing what you said above and I got the same issue. The UI freezes up, the image only appears for one of the cells.

The best thing you can do is to store your image as a UIImage allocated, and to have a helper function which returns a new UIImageView per cell.

Using your current method (without a stored UIImage) you might do:

-(UIImageView *) makeCheckmarkOffAccessoryView
{
    return [[[UIImageView alloc] initWithImage:
        [UIImage imageNamed:@"checkmarkOff.png"]] autorelease];
}

And then do

cell.accessoryView = [self makeCheckmarkOffAccessoryView];

As you may be aware, UIImages on the other hand may be used any number of times. a UIImageView doesn't take up a lot of space, so you can easily have a bunch of those without worrying.

To expand on the one place only deal, imagine that you add a UIView to two places at the same time.

What will [ob removeFromSuperview] do for this object? Will it remove the view from both places? From one of them only? Which value will be returned when you request [ob superview]? Clearly the UI is not made to handle what you're asking for.

like image 155
Kalle Avatar answered Oct 22 '22 20:10

Kalle