UISegmentedControl Best Practice

Viewed 19201

I'm trying to work out the "best" way to use a UISegmentedControl for an iPhone application. I've read a few posts here on stackoverflow and seen a few people's ideas, but I can't quite sort out the best way to do this. The posts I'm referring to are:

Changing Views from UISegmentedControl and How do I use a UISegmentedControl to switch views?

It would seem that the options are:

  • Add each of the views in IB and lay them out on top of each other then show/hide them
  • Create each of the subviews separately in IB, then create a container in the main view to populate with the subview that you need
  • Set up one really tall or really wide UIView and animate it left/right or up/down depending on the selected segment
  • Use a UITabBarController to swap out the subviews - seems silly
  • For tables, reload the table and in cellForRowAtIndex and populate the table from different data sources or sections based on the segment option selected (not the case for my app)

So which approach is best for subview/non-table approaches? Which is the easiest to implement? Could you share some sample code to the approach?

Thanks!

3 Answers

I'd go with the second option you mention, creating the subviews in IB and swapping them in and out of a main view. This would be a good opportunity to use UIViewController, unsubclassed: in your initial setup, create a controller using -initWithNibName:bundle: (where the first parameter is the name of the NIB containing the individual subview, and the second parameter is nil) and add its view as a subview of your main view as necessary. This will help keep your memory footprint low: the default behavior of a UIViewController when receiving a memory warning is to release its view if it has no superview. As long as you remove hidden views from the view hierarchy, you can keep the controllers in memory and not worry about releasing anything.

(edited in response to comment:)

You don't need to subclass UIViewController, but you do need separate XIBs for each view. You also don't need to add anything to the containing view in IB.

Instance variables, in the interface of whatever class is handling all this:

 UIViewController *controllerOne;
 UIViewController *controllerTwo;

 UIViewController *currentController;

 IBOutlet UIView *theContainerView;

In your setup (-applicationDidFinishLaunching: or whatever)

 controllerOne = [[UIViewController alloc] initWithNibName:@"MyFirstView" bundle:nil];
 controllerTwo = [[UIViewController alloc] initWithNibName:@"MySecondView" bundle:nil];

To switch to a controller:

 - (void)switchToController:(UIViewController *)newCtl
 {
      if(newCtl == currentController)
           return;
      if([currentController isViewLoaded])
           [currentController.view removeFromSuperview];

      if(newCtl != nil)
           [theContainerView addSubview:newCtl.view];

      currentController = newCtl;
 }

Then just call that with, e.g.,

 [self switchToController:controllerOne];
Related