Переключение ViewControllers с UISegmentedControl в iOS5
Я пытаюсь что-то очень просто, но почему-то я не могу заставить его работать. Все, что я пытаюсь сделать, это переключение между 2-мя контроллерами просмотра с помощью UISegmentedControl, как вы можете видеть это, например, в приложении App Store на вкладке "Основные".
Я использую iOS5 и раскадровки.
Здесь моя строка Storyboad:
![enter image description here]()
Итак, у меня есть root View Controller и два 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
Я могу запустить событие switch и зарегистрировать текущий выбранный индекс. Но я не знаю, куда идти отсюда.
Может кто-то может обратить мое внимание на определенное направление...?
Ответы
Ответ 1
Этот код работает очень хорошо для вашей цели, я использую его для одного из моих новых приложений.
Он использует новые API-интерфейсы UIViewController, которые позволяют UIViewControllers внутри ваших собственных UIViewControllers без проблем с пересылкой вручную, например 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;
}
Я получил этот материал из главы 22 книги Рей Вендерлиха iOS5 по учебнику.
К сожалению, у меня нет общедоступной ссылки на учебник. Но есть видео WWDC 2011 под названием "Реализация UIViewController Containment"
ИЗМЕНИТЬ
self.typeSegmentedControl
- это выход для вашего UISegmentedControl
self.contentView
- это выход для вашего вида контейнера
self.currentViewController
- это просто свойство, которое мы используем для хранения используемого в настоящее время UIViewController
Ответ 2
Это решение Матиаса Бауха, но подумал о том, чтобы поделить его в Свифт в любом случае!
Edit:
Добавление ссылки на готовое демонстрационное приложение 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
}
Ответ 3
Для кого-то нужно реализовать то же самое в быстрой
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!
}
}
Раскадровка
![введите описание изображения здесь]()
Ответ 4
A - контроллер корневого представления, а B, C - контроллер под-представления.
Когда вы нажимаете сегмент, добавьте контроллер подзаголовка.
результат
![result]()
дизайн
![design]()
код
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()
}
}
Ответ 5
Вы можете встроить свой контроллер начального представления в контроллер навигации. Сделайте это, выбирая контроллер просмотра в раскадровке, затем Editor- > Embed in > Navigation Controller.
В вашем методе indexDidChangeForSegmentedControl: вы просто нажимаете соответствующий контроллер представления в стек навигации:
- (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl*)segmentedControl
{
[self.navigationController pushViewController:[self.viewControllers objectAtIndex:[segmentedControl.selectedIndex]] animated:YES];
}
Но ваш подход не имеет особого смысла, когда вы используете раскадровки.
Я не знаю, можно ли подключить одну сегментированную кнопку управления к контроллеру вида с помощью segues. Просто попробуйте.