Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switching ViewControllers with UISegmentedControl in iOS5

I am trying something very simple but somehow I can't get it to work. All I try to do is switching between 2 View Controllers using an UISegmentedControl as you can see it for example in the App Store application in the Highlights tab.

I am using iOS5 and Storyboards.

Here's my Storyboad line up:

enter image description here

So I have a root View Controller and two UITableViews - This 2 TableViews I want to switch.

Here's how the implementation file looks like

#import "SegmentedLocationViewController.h" #import "PastEventsLocationViewController.h" #import "FutureEventsLocationViewController.h"  @interface SegmentedLocationViewController() @property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedControl; @property (strong, nonatomic) NSArray *viewControllers; @end   @implementation SegmentedLocationViewController  @synthesize segmentedControl = _segmentedControl; @synthesize viewControllers = _viewControllers;  - (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl*)segmentedControl {     NSLog(@"index: %d", segmentedControl.selectedSegmentIndex); }  - (void)setupViewControllers {     PastEventsLocationViewController *pastEventsLocationViewController = [[PastEventsLocationViewController alloc] initWithStyle:UITableViewStylePlain];     FutureEventsLocationViewController *futureEventsLocationViewController = [[FutureEventsLocationViewController alloc] initWithStyle:UITableViewStylePlain];      self.viewControllers = [NSArray arrayWithObjects:pastEventsLocationViewController, futureEventsLocationViewController, nil]; }  - (void)setupUI {     [self.segmentedControl addTarget:self action:@selector(indexDidChangeForSegmentedControl:) forControlEvents:UIControlEventValueChanged]; }  // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad {     [super viewDidLoad];     [self setupViewControllers];     [self setupUI]; }  - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {     return YES; }  @end 

I can trigger the switch event and can log the currently selected index. But I don't have any idea where to go from here.

Maybe someone can turn my attention towards a certain direction...?

like image 706
MrBr Avatar asked Feb 02 '12 10:02

MrBr


2 Answers

This code works pretty well for your purpose, I use it for one of my new apps.
It uses the new UIViewController containment APIs that allow UIViewControllers inside your own UIViewControllers without the hassles of manually forwarding stuff like viewDidAppear:

- (void)viewDidLoad {     [super viewDidLoad];     // add viewController so you can switch them later.      UIViewController *vc = [self viewControllerForSegmentIndex:self.typeSegmentedControl.selectedSegmentIndex];     [self addChildViewController:vc];     vc.view.frame = self.contentView.bounds;     [self.contentView addSubview:vc.view];     self.currentViewController = vc; } - (IBAction)segmentChanged:(UISegmentedControl *)sender {     UIViewController *vc = [self viewControllerForSegmentIndex:sender.selectedSegmentIndex];     [self addChildViewController:vc];     [self transitionFromViewController:self.currentViewController toViewController:vc duration:0.5 options:UIViewAnimationOptionTransitionFlipFromBottom animations:^{         [self.currentViewController.view removeFromSuperview];         vc.view.frame = self.contentView.bounds;         [self.contentView addSubview:vc.view];     } completion:^(BOOL finished) {         [vc didMoveToParentViewController:self];         [self.currentViewController removeFromParentViewController];         self.currentViewController = vc;     }];     self.navigationItem.title = vc.title; }  - (UIViewController *)viewControllerForSegmentIndex:(NSInteger)index {     UIViewController *vc;     switch (index) {         case 0:             vc = [self.storyboard instantiateViewControllerWithIdentifier:@"FooViewController"];             break;         case 1:             vc = [self.storyboard instantiateViewControllerWithIdentifier:@"BarViewController"];             break;     }     return vc; } 

I got this stuff from chapter 22 of Ray Wenderlichs book iOS5 by tutorial. Unfortunately I don't have a public link to a tutorial. But there is a WWDC 2011 video titled "Implementing UIViewController Containment"

EDIT

self.typeSegmentedControl is outlet for your UISegmentedControl

self.contentView is outlet for your container view

self.currentViewController is just a property that we're using to store our currently used UIViewController

like image 77
Matthias Bauch Avatar answered Sep 25 '22 05:09

Matthias Bauch


It's Matthias Bauch solution, but thought of sharing it in Swift anyway! Edit: Adding a link to a Swift 2.0 ready made demo app. https://github.com/ahmed-abdurrahman/taby-segmented-control

var currentViewController: UIViewController? @IBOutlet weak var contentView: UIView! @IBOutlet weak var segmentedControl: UISegmentedControl!  @IBAction func switchHappeningTabs(sender: UISegmentedControl) {     if let vc = viewControllerForSelectedSegmentIndex(sender.selectedSegmentIndex) {         self.addChildViewController(vc)         self.transitionFromViewController(self.currentViewController!, toViewController: vc, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromRight, animations: {             self.currentViewController!.view.removeFromSuperview()             vc.view.frame = self.contentView.bounds             self.contentView.addSubview(vc.view)             }, completion: { finished in                 vc.didMoveToParentViewController(self)                 self.currentViewController!.removeFromParentViewController()                 self.currentViewController = vc             }         )             } }  override func viewDidLoad() {     super.viewDidLoad()      if let vc = self.viewControllerForSelectedSegmentIndex(self.segmentedControl.selectedSegmentIndex) {         self.addChildViewController(vc)         self.contentView.addSubview(vc.view)         self.currentViewController = vc     } }  func viewControllerForSelectedSegmentIndex(index: Int) -> UIViewController? {     var vc: UIViewController?     switch index {     case 0:             vc = self.storyboard?.instantiateViewControllerWithIdentifier("FooViewController") as? UIViewController     case 1:             vc = self.storyboard?.instantiateViewControllerWithIdentifier("BarViewController") as? UIViewController     default:         return nil     }      return vc } 
like image 44
Abdurrahman Avatar answered Sep 22 '22 05:09

Abdurrahman