views:

808

answers:

1

I have added a refresh UIBarButtonItem to my navigation bar on my iPhone app. When the user taps the button I'd like the refresh button to change to the animated activity indicator and once the operation (in this case a download) is complete switch the activity indicator back to the refresh button.

I have added the refresh button using IB. Then on the button tap I create a new activity indicator and keep an pointer to the original refresh button. Like so:

refreshButtonItem = self.navigationItem.leftBarButtonItem;
if (activityButtonItem == nil)
{
    activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 20,20)];
    activityButtonItem = [[UIBarButtonItem alloc]initWithCustomView:activityIndicator];

}
self.navigationItem.leftBarButtonItem = activityButtonItem;
[activityIndicator startAnimating];

So far, so good. Problem is that when my download finishes and I try to re-add the refresh button (using the following):

[activityIndicator stopAnimating];
self.navigationItem.leftBarButtonItem = refreshButtonItem;

I get the following error:
[UIBarButtonItem retain]: message sent to deallocated instance

I'm not explicitly calling release.

A) When/where is this being deallocated

B) Is there a better way to achieve what I'm looking for?

+1  A: 

When you assign the activityButtonItem to leftBarButtonItem, the item that leftBarButtonItem used to point to is released. The leftBarButtonItem (and all properties with the retain option) are implemented similarly to this:

- (void)leftBarButtonItem:(UIBarButtonItem *)newItem {
  if (newItem != self.leftBarButtonItem) {
    [self.leftBarButtonItem release];
    leftBarButtonItem = [newItem retain];
  }
}

If you want to use the refreshButtonItem after reassigning the leftBarButtonItem, change your first line to:

refreshButtonItem = [self.navigationItem.leftBarButtonItem retain];

Martin Gordon
Worked like a charm! Thanks.
cagreen