2013-04-17 7 views
21

Ich verwende eine Storyboard-Containeransicht. Ich habe also einen View-Controller, der eine Containeransicht enthält. Ich habe eine zweite, kleinere Ansicht im Storyboard, die über einen Embed-Segue in diesen Container eingebettet ist. So weit, ist es gut.Containeransicht dynamisch wechseln

Jetzt möchte ich in der Lage sein, den Inhalt dieser Containeransicht dynamisch zu wechseln, wenn der Benutzer auf eine Schaltfläche klickt. Die Schaltfläche befindet sich auf der größeren Hauptansicht. Ich habe einen anderen View-Controller derselben Größe erstellt und ihm eine andere Storyboard-ID gegeben.

Ich kann jedoch nicht herausfinden, wie der Schalter codiert wird. Ich kann nur einen einzigen eingebetteten Übergang für diesen Container erstellen.

Jede Hilfe dankbar erhalten.

Antwort

39

Sie müssen die benutzerdefinierte Containeransicht Controller API verwenden, um die Controller zu wechseln. Der folgende Code zeigt eine Möglichkeit, dies zu tun. In diesem Projekt hatte ich eine segmentierte Steuerung im Hauptansicht-Controller (der mit der Containeransicht), der zwischen den beiden Controllern schaltet. initialVC ist der Controller, der in IB eingebettet ist, und substitutiveVC ist der, zu dem ich wechsele. Die Eigenschaft container ist ein IBOutlet für die Containeransicht.

- (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; 
          }]; 
} 

Nach Edit:

Wenn Sie ohne Animation auf den neuen Controller gehen wollen, können Sie es wie folgt (dies ersetzt den Code, den ich unter Fall hatte 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

Hey, danke, das ist grandios. Eine Sache - Um das genaue Ergebnis zu erhalten, das ich wollte (ein gerader Austausch - keine Animation), habe ich Ihre moveToNewController-Methode auf duration: 0 und options: UIViewAnimationOptionTransitionNone geändert. Ein Teil des Codes, einschließlich der Struktur des Abschlussblocks, erscheint jedoch redundant. Gibt es eine einfachere Möglichkeit, die endgültige Methode für einen direkten (nicht animierten) Tausch zu schreiben? –

+0

@JamesWhite, ich habe meine Antwort bearbeitet, um zu zeigen, wie es ohne Animation funktioniert. – rdelmar

+0

Du bist ein Champion. –

4

rdelmar's answer zu Swift Syntax umgewandelt

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

Wenn Sie mit mehr als 2 Kind View-Controller umgehen, es ist eine gute Idee, sie in einem Array zu speichern. Außerdem müssen Sie jedes Mal Einschränkungen anwenden, wenn Sie der Containeransicht eine neue Unteransicht hinzufügen. Hier ist eine modifizierte Version der akzeptierten Antwort (mit Swift 2-Syntax):

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

Wo fügen Sie "containerView" View-Controller hinzu? – Satyam

Verwandte Themen