segmented how example control ios uiviewcontroller uikit uisegmentedcontrol

how - Conmutación de ViewControllers con UISegmentedControl en iOS5



swift 4 segmented control example (5)

¡Es la solución de Matthias Bauch, pero de todos modos pensé en compartirla en Swift! Editar: Agregar un enlace a una aplicación de demostración preparada para Swift 2.0. 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 }

Estoy intentando algo muy simple, pero de alguna manera no puedo hacer que funcione. Todo lo que intento hacer es cambiar entre 2 Controladores de Vista usando un UISegmentedControl como lo puede ver, por ejemplo, en la aplicación App Store en la pestaña Destacados.

Estoy usando iOS5 y Storyboards.

Aquí está mi alineación de Storyboad:

Así que tengo un controlador de vista raíz y dos UITableViews: estas 2 TableViews quiero cambiar.

Así es como se ve el archivo de implementación

#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

Puedo activar el evento de cambio y puedo registrar el índice seleccionado actualmente. Pero no tengo idea de dónde ir desde aquí.

¿Tal vez alguien pueda dirigir mi atención hacia una determinada dirección ...?


A es controlador de vista raíz y B, C es controlador de vista secundaria. Al hacer clic en segmento, agregue el controlador de subvista.

resultado

diseño

código

import UIKit class SegmentViewController: UIViewController { @IBOutlet weak var containerView: UIView! var leftViewController: LeftViewController! var rightViewController: RightViewController! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. if let sb = storyboard { leftViewController = sb.instantiateViewControllerWithIdentifier("leftViewController") as! LeftViewController switchViewController(from: nil, to: leftViewController) } else { print("storyboard is nil") } } func switchViewController(from fromVC: UIViewController?, to toVC: UIViewController?) { if let from = fromVC { from.willMoveToParentViewController(nil) from.view.removeFromSuperview() from.removeFromParentViewController() } else { print("fromVC is nil") } if let to = toVC { self.addChildViewController(to) to.view.frame = CGRectMake(0, 0, containerView.frame.width, containerView.frame.height) self.containerView.insertSubview(to.view, atIndex: 0) to.didMoveToParentViewController(self) } else { print("toVC is nil") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. removeViewController() } func removeViewController() { if let leftVC = leftViewController { if let _ = leftVC.parentViewController { print("leftVC is using") } else { print("set leftVC = nil") leftViewController = nil } } if let rightVC = rightViewController { if let _ = rightVC.parentViewController { print("rightVC is using") } else { print("set rightVC = nil") rightViewController = nil } } } @IBAction func onSegmentValueChanged(sender: UISegmentedControl) { UIView.beginAnimations("xxx", context: nil) UIView.setAnimationDuration(0.4) UIView.setAnimationCurve(.EaseInOut) switch sender.selectedSegmentIndex { case 0: UIView.setAnimationTransition(.FlipFromRight, forView: self.containerView, cache: true) if let leftVC = leftViewController { switchViewController(from: rightViewController, to: leftVC) } else { if let sb = storyboard { leftViewController = sb.instantiateViewControllerWithIdentifier("leftViewController") as! LeftViewController switchViewController(from: rightViewController, to: leftViewController) } else { print("storyboard is nil") } } default: UIView.setAnimationTransition(.FlipFromLeft, forView: self.containerView, cache: true) if let rightVC = rightViewController { switchViewController(from: leftViewController, to: rightVC) } else { if let sb = storyboard { rightViewController = sb.instantiateViewControllerWithIdentifier("rightViewController") as! RightViewController switchViewController(from: leftViewController, to: rightViewController) } else { print("storyboard is nil") } } } UIView.commitAnimations() } }


Este código funciona bastante bien para su propósito, lo uso para una de mis nuevas aplicaciones.
Utiliza las nuevas API de contención UIViewController que permiten UIViewControllers dentro de sus propios UIViewControllers sin las molestias de reenviar manualmente cosas como 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; }

Obtuve este material del capítulo 22 del libro de Ray Wenderlichs iOS5 por tutorial . Lamentablemente, no tengo un enlace público a un tutorial. Pero hay un video de la WWDC 2011 titulado "Implementación de la contención de UIViewController"

EDITAR

self.typeSegmentedControl es la salida para su UISegmentedControl

self.contentView es una salida para su vista de contenedor

self.currentViewController es solo una propiedad que estamos usando para almacenar nuestro UIViewController utilizado actualmente


Para alguien quiere implementar lo mismo en forma rápida

import UIKit class HomeController: UIViewController { var currentViewController:UIViewController? @IBOutlet weak var homeController: UIView! override func viewDidLoad() { super.viewDidLoad() let initialController:UIViewController = self.viewControllerForSegmentedIndex(0) self.addChildViewController(initialController) initialController.view.frame = self.homeController.bounds self.homeController.addSubview(initialController.view) self.currentViewController = initialController } @IBAction func segmentChanged(sender: UISegmentedControl) { let viewCOntroller:UIViewController = viewControllerForSegmentedIndex(sender.selectedSegmentIndex) self.addChildViewController(viewCOntroller) self.transitionFromViewController(self.currentViewController!, toViewController: viewCOntroller, duration: 0.5, options: UIViewAnimationOptions.TransitionFlipFromBottom, animations: { self.currentViewController?.view.removeFromSuperview() viewCOntroller.view.frame = self.homeController.bounds self.homeController.addSubview(viewCOntroller.view) }, completion:{ finished in viewCOntroller.didMoveToParentViewController(self) self.currentViewController?.removeFromParentViewController() self.currentViewController = viewCOntroller }) } func viewControllerForSegmentedIndex(index:Int) -> UIViewController { var viewController:UIViewController? switch index { case 0: viewController = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardIdForFirstController") break case 1: viewController = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardIdForSecondController") break case 2: viewController = self.storyboard?.instantiateViewControllerWithIdentifier("StoryboardIdForThirdController") break default: break } return viewController! } }

Vista del guión gráfico


Puede incrustar su controlador de vista inicial en un controlador de navegación. Haga eso seleccionando el controlador de vista en el guión gráfico, luego Editor-> Insertar en> Controlador de navegación.

En su método indexDidChangeForSegmentedControl: simplemente inserta el controlador de vista correspondiente en la pila de navegación:

- (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl*)segmentedControl { [self.navigationController pushViewController:[self.viewControllers objectAtIndex:[segmentedControl.selectedIndex]] animated:YES]; }

Pero su enfoque no tiene demasiado sentido cuando está usando storyboards. No sé si puede cablear un solo botón de control segmentado a un controlador de visualización usando los segmentos. Solo inténtalo.