在iOS5中使用UISegmentedControl切换ViewController

我正在尝试一些非常简单的东西,但不知何故我无法得到它的工作。 我所要做的就是使用UISegmentedControl在2个视图控制器之间进行切换,例如您可以在Highlights选项卡的App Store应用程序中看到它。

我正在使用iOS5和故事板。

这是我的Storyboad排队:

在这里输入图像说明

所以我有一个根视图控制器和两个UITableViews – 这2个TableViews我想切换。

这是实现文件的样子

#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 

我可以触发切换事件,并可以logging当前select的索引。 但我不知道该从哪里出发。

也许有人可以把我的注意力转向一个特定的方向…?

这段代码对你的目的来说工作得很好,我把它用于我的新应用程序之一。
它使用新的UIViewController遏制API,允许您自己的UIViewControllers内的UIViewControllers没有手动转发像viewDidAppear:东西的麻烦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; } 

我从Ray Wenderlichs的第22章那本书中得到了这个东西。 不幸的是我没有公共的教程链接。 但是有一个名为“实现UIViewController控制”的WWDC 2011video

编辑

self.typeSegmentedControl是你的UISegmentedControl出口

self.contentView是你的容器视图的出口

self.currentViewController只是我们用来存储我们目前使用的UIViewController一个属性

这是Matthias Bauch的解决scheme,但是想到在Swift中分享它! 编辑:添加一个链接到一个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 } 

对于想快速实施的人来说

 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! } } 

故事板视图

在这里输入图像说明

A是根视图控制器,B,C是子视图控制器。 当你点击段时,添加子视图控制器。

结果

结果

devise

设计

 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() } } 

您可以将您的初始视图控制器embedded到导航控制器中。 通过select故事板中的视图控制器,然后编辑器 – >embedded – >导航控制器。

在您的indexDidChangeForSegmentedControl:方法中,您只需将相应的视图控制器推送到导航堆栈:

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

但是,当你使用故事板时,你的方法并没有太多意义。 我不知道是否可以使用segues将单个分段控制button连接到视图控制器。 去尝试一下。