2013-04-17 5 views
21

Я использую представление контейнера раскадровки. Поэтому у меня есть контроллер вида, содержащий контейнерный вид. У меня есть второй, меньший вид в раскадровке, который встроен в этот контейнер через встроенный segue. Все идет нормально.Динамический просмотр контейнера контейнера

Теперь я хотел бы иметь возможность динамически переключаться с содержимым этого вида контейнера, когда пользователь нажимает кнопку. Кнопка будет на основном, большем, представлении. Я сделал еще один контроллер представления того же меньшего размера и дал ему другой идентификатор раскадровки.

Однако я не могу понять, как закодировать переключатель. Я могу создать только один встроенный segue для этого контейнера.

Любая помощь с благодарностью получена.

ответ

39

Для переключения контроллеров вам необходимо использовать пользовательский контроллер представления контейнера api. Следующий код показывает один из способов сделать это. В этом проекте у меня был сегментированный элемент управления в главном контроллере представления (тот, который имеет вид контейнера), который переключается между двумя контроллерами. initialVC - это контроллер, встроенный в IB, а substituteVC - тот, к которому я перехожу. Свойство, контейнер, представляет собой IBOutlet для представления контейнера.

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.initialVC = self.childViewControllers.lastObject; 
    self.substituteVC = [self.storyboard instantiateViewControllerWithIdentifier:@"Substitute"]; 
    self.currentVC = self.initialVC; 
} 

-(IBAction)switchControllers:(UISegmentedControl *)sender { 

    switch (sender.selectedSegmentIndex) { 
     case 0: 
      if (self.currentVC == self.substituteVC) { 
       [self addChildViewController:self.initialVC]; 
       self.initialVC.view.frame = self.container.bounds; 
       [self moveToNewController:self.initialVC]; 
      } 
      break; 
     case 1: 
      if (self.currentVC == self.initialVC) { 
       [self addChildViewController:self.substituteVC]; 
       self.substituteVC.view.frame = self.container.bounds; 
       [self moveToNewController:self.substituteVC]; 
      } 
      break; 
     default: 
      break; 
    } 
} 


-(void)moveToNewController:(UIViewController *) newController { 
    [self.currentVC willMoveToParentViewController:nil]; 
    [self transitionFromViewController:self.currentVC toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionFlipFromLeft animations:nil 
          completion:^(BOOL finished) { 
           [self.currentVC removeFromParentViewController]; 
           [newController didMoveToParentViewController:self]; 
           self.currentVC = newController; 
          }]; 
} 

После Edit:

Если вы хотите перейти на новый контроллер, без анимации, вы можете сделать это, как это (это заменяет код, который я имел под случай 1).

[self addChildViewController:self.substituteVC]; 
[self.substituteVC didMoveToParentViewController:self]; 
self.substituteVC.view.frame = self.container.bounds; 
[self.container addSubview:self.substituteVC.view]; 
[self.currentVC removeFromParentViewController]; 
+0

Эй, спасибо, это потрясающе. Одна вещь - получить точный результат, который я хотел (прямой обмен - без анимации), я изменил метод moveToNewController на длительность: 0 и опции: UIViewAnimationOptionTransitionNone. Но некоторые из кода, включая структуру блока завершения, кажутся излишними. Есть ли более простой способ написать окончательный метод прямого (неанимированного) обмена? –

+0

@JamesWhite, я отредактировал свой ответ, чтобы показать, как это сделать без анимации. – rdelmar

+0

Ты чемпион. –

4

rdelmar's answer преобразуется в Swift синтаксисом

override func viewDidLoad() { 
     super.viewDidLoad() 

     self.initialVC = self.childViewControllers.last 
     self.substituteVC = self.storyboard!.instantiateViewControllerWithIdentifier("Substitute") 
     self.currentVC = self.initialVC; 

} 
    @IBAction func switchControllers(sender: UISegmentedControl) { 
     switch sender.selectedSegmentIndex{ 
      case 0: 
       if (self.currentVC == self.substituteVC) { 
        self.addChildViewController(self.initialVC) 
        //self.initialVC.view.frame = self.containerView.bounds 
        moveToNewController(self.initialVC) 
       } 
      case 1: 
       if (self.currentVC == self.initialVC) { 
        self.addChildViewController(self.substituteVC) 
        //self.substituteVC.view.frame = self.containerView.bounds 
        moveToNewController(self.substituteVC) 
       } 
      default: 
      break; 
     } 
    } 

    func moveToNewController(newController : UIViewController){ 
     self.currentVC.willMoveToParentViewController(nil) 
     self.transitionFromViewController(
      self.currentVC!, 
      toViewController: newController, 
      duration: 0.2, 
      options: UIViewAnimationOptions.TransitionCrossDissolve, 
      animations: nil, 
      completion: { finished in 
       self.currentVC.removeFromParentViewController() 
       newController.didMoveToParentViewController(self) 
       self.currentVC = newController 
     }) 

    } 
0

Если вы имеете дело с контроллерами зрения более 2 детей, это хорошая идея, чтобы сохранить их в массиве. Кроме того, вам придется применять ограничения каждый раз, когда вы добавляете новое представление в представление контейнера. Ниже приведена модифицированная версия принятого ответа (с использованием синтаксиса Swift 2):

import UIKit 

class FooBarViewController: UIViewController 
{ 
    // MARK: - IBOutlets 

    @IBOutlet weak var containerView: UIView! 

    // MARK: - Properties 

    var vcs = [UIViewController]() 
    var currentVC: UIViewController! 

    // MARK: - ViewController Lifecycle 

    override func viewDidLoad() 
    { 
     super.viewDidLoad() 

     vcs.append(childViewControllers.last!) 
     vcs.append(storyboard!.instantiateViewControllerWithIdentifier("FooViewControler"))  
     vcs.append(storyboard!.instantiateViewControllerWithIdentifier("BarViewController")) 
     currentVC = vcs[0] 

     for vc in vcs { 
      vc.view.frame = containerView.bounds 
     } 
    } 

    // MARK: - Methods 

    func switchToViewController(targetVC: UIViewController) 
    { 
     addChildViewController(targetVC) 
     currentVC.willMoveToParentViewController(nil) 

     transitionFromViewController(
      currentVC, 
      toViewController: targetVC, 
      duration: 0.0, // 0.3 
      options: .TransitionNone, // .TransitionCrossDissolve, 
      animations: nil, 
      completion: { finished in 
       self.currentVC.removeFromParentViewController() 
       targetVC.didMoveToParentViewController(self) 
       self.currentVC = targetVC 
       self.applyConstraints() 
     }) 
    } 

    func applyConstraints() 
    { 
     let viewsDict = ["newSubview": currentVC.view] 

     currentVC.view.translatesAutoresizingMaskIntoConstraints = false 

     containerView.addConstraints(
      NSLayoutConstraint.constraintsWithVisualFormat("H:|[newSubview]|", 
       options: NSLayoutFormatOptions(rawValue: 0), 
       metrics: nil, 
       views: viewsDict)) 

     containerView.addConstraints(
      NSLayoutConstraint.constraintsWithVisualFormat("V:|[newSubview]|", 
       options: NSLayoutFormatOptions(rawValue: 0), 
       metrics: nil, views: 
       viewsDict)) 
    } 

    // MARK: - IBActions 

    @IBAction func switchControllers(sender: UISegmentedControl) 
    { 
     let i = sender.selectedSegmentIndex 

     if currentVC != vcs[i] { 
      self.addChildViewController(vcs[i]) 
      switchToViewController(vcs[i]) 
     } 
    } 
} 
+0

Где вы добавляете контроллеры представлений в "containerView"? – Satyam

Смежные вопросы