views:

49

answers:

1

I'm building a segmented control within my viewDidLoad method, like so:

NSArray *tabitems = [NSArray arrayWithObjects:@"ONE", @"TWO", nil];
UISegmentedControl *tabs = [[UISegmentedControl alloc] initWithItems:tabitems];
tabs.segmentedControlStyle = UISegmentedControlStyleBar;
tabs.frame = CGRectMake(185.0, 7.0, 130.0, 30.0);
tabs.selectedSegmentIndex = 0;
[self.navigationController.navigationBar addSubview:tabs];
[tabs release];

But when the user goes Back in the uinavigationcontroller hierarchy, the segmented controller stays on the navigation bar. How would I get rid of it? Or am I doing something fundamentally wrong?


EDIT

Following Alex's suggestions, I propertized tabs and tried:

  NSArray *tabItems = [NSArray arrayWithObjects:@"FAQs", @"Terms", nil];
  self.tabs = [[UISegmentedControl alloc] initWithItems:tabItems];

but I'm not sure it's a good idea to alloc a property;

And I'm using

  [self.tabs removeFromSuperview];

in my viewWillDisappear. Is that enough?

+2  A: 

Retain a reference to the segmented control in your view controller (i.e define tabs as a property in the view controller's header file).

Override the view controller's -viewWillDisappear: method, and remove the segmented control from the navigation bar there, using the control's -removeFromSuperview method.

EDIT

You would still alloc-init your segmented control tabs in -viewDidLoad. You just need to set up a retain property for tabs in your view controller's header, and move the control's release statement to the view controller's dealloc method.

Read the "Properties" section of this Objective-C tutorial for an introduction to properties and how to set them up.

The way to override a method is as follows:

- (ReturnClass) methodNameToOverride:args {
    [super methodNameToOverride:args];
    // your code goes here...
}

In the case of -viewWillDisappear:, this method gets called when your view controller is about to disappear, such as when it gets popped off the navigation stack. This is a great place to put code that manages clean-up of view-controller-specific items, like your segmented control:

- (void) viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [tabs removeFromSuperview];
}

EDIT 2

If your property is set as follows:

@property (nonatomic, retain) UISegmentedControl *tabs;

then you are going to retain anything you set self.tabs equal to.

Your code here:

self.tabs = [[UISegmentedControl alloc] initWithItems:...];

will create a memory leak, because you are retaining this object: [[UISegmentedControl alloc] init] — but you never release [[UISegmentedControl alloc] init] itself. This is bad.

Instead, use autorelease on the right side, i.e.:

self.tabs = [[[UISegmentedControl alloc] initWithItems:...] autorelease];

The tabs property retains its own reference to the initialized segmented control. That initialized segmented control is itself released properly at some later point. So no more memory leak.

Alex Reynolds
Thanks. how would I set up the segmented control without alloc/init-ing it? And can you give me the line of code required in the viewWillDisappear method. Thanks
cannyboy
changed orig question
cannyboy
Please see edits.
Alex Reynolds
Thanks for 'Edit 2'. I had everything in place except the autorelease thing.
cannyboy