2016-11-24 17 views
2

Я хочу, чтобы достичь очень простой задачи изменяющей в ViewController из контейнера View, нажав на кнопку:Swift: Переключение между NSViewController внутри контейнерного View/NSView

enter image description here

В моем примере ViewController1 встроено в представление контейнера с помощью Interface Builder. Нажав кнопку ViewController2, я хочу изменить представление на второй ViewController.

Я смущен, потому что сам контейнер выглядит как NSView, если я создаю выход, и насколько я знаю, NSView не может содержать VC. Очень ценю вашу помощь!

ответ

5

Сразу отметим, что для того, чтобы это работало, вы должны добавить раскадровки идентификаторы контроллеров зрения, которые могут с помощью своего видеоредактора затем выберите Удостоверение инспектора в правой панели, а затем ввести Storyboard ID в Identity подкатегории ,

Тогда эта реализация ViewController обеспечит то, что вы ищете.

import Cocoa 

class ViewController: NSViewController { 

    // link to the NSView Container 
    @IBOutlet weak var container : NSView! 

    var vc1 : ViewController1! 
    var vc2 : ViewController2! 

    var vc1Active : Bool = false 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Make sure to set your storyboard identiefiers on ViewController1 and ViewController2 
     vc1 = NSStoryboard(name: "name", bundle: nil).instantiateController(withIdentifier: "ViewController1") as! ViewController1 
     vc2 = NSStoryboard(name: "name", bundle: nil).instantiateController(withIdentifier: "ViewController2") as! ViewController2 

     self.addChildViewController(vc1) 
     self.addChildViewController(vc2) 
     vc1.view.frame = self.container.bounds 
     self.container.addSubview(vc1.view) 
     vc1Active = true 

    } 

    // You can link this action to both buttons 
    @IBAction func switchViews(sender: NSButton) { 

     for sView in self.container.subviews { 
      sView.removeFromSuperview() 
     } 

     if vc1Active == true { 

      vc1Active = false 
      vc2.view.frame = self.container.bounds 
      self.container.addSubview(vc2.view) 

     } else { 

      vc1Active = true 
      vc1.view.frame = self.container.bounds 
      self.container.addSubview(vc1.view) 
     } 

    } 
} 
+0

Спасибо @Wes за ваш подробный ответ! У меня ошибка в строке 'self.container.addSubview (vc1.view)': »В представлении контейнера есть непредвиденные подпункты«. Поэтому я попытался удалить все подзапросы (как вы делали в вашем func 'switchViews' сначала, но это не сработало (ошибка остается прежней). Любые идеи? – ixany

+0

@ixany несколько вещей. Во-первых, измените свой код, чтобы отразить редактирование, которое я сделал (небольшие изменения, чтобы предотвратить запутывающие представления). Также удалите взаимосвязь вставки между 'Container' и' ViewController1'. Сделайте это, щелкнув правой кнопкой мыши 'Container' в IB и удалив соединение. – Wes

+0

Еще раз спасибо @Wes! были правы, мне пришлось удалить embed/segue в 'ViewController1' в IB. Я принял ваш ответ, но у вас есть еще один вопрос: добавляет ли и снимает ли subviews для этой задачи наилучшую практику? При ее реализации я также нашел' .removeChildViewController() 'и подумал, что это может быть лучше с точки зрения производительности. В subview-решении приложение загружает все возможные VC, даже когда они никогда не появятся. Существуют ли другие преимущества добавления/удаления subviews? – ixany

1

Возможно, это поздний ответ, но я все равно отправлю свое решение. Надеюсь, это поможет кому-то.

Я встроил NSTabViewController в ContainerView. Тогда, чтобы не видеть сверху вкладки я сделал это:

  • перейти к NSTabViewController в раскадровке

  • в стиле изменения атрибутов инспектора быть выбрано

  • затем нажмите на TabView в Tab Bar View Controller, и набор стилей, чтобы быть "tabless" see image here

После т его вам нужно:

  • магазин tabViewController ссылка на mainViewController для того, чтобы выбрать вкладки из кода
  • добавить кнопку mainViewController (где ваш контейнер есть), с которым вы будете менять вкладки в tabViewController.

Вы делаете это, сохраняя ссылку на tabViewController при переопределении подготовки к функции segue. Вот мой код:

сначала добавить свойство к mainViewController

private weak var tabViewController: NSTabViewController? 

затем переопределить эту функцию и сохранить ссылку на tabViewController:

override func prepare(for segue: NSStoryboardSegue, sender: Any?) { 
      guard let tabViewController = segue.destinationController 
       as? NSTabViewController else { return } 

      **self.tabViewController = tabViewController as? NSTabViewController** 

     } 

После этого вы будете иметь ссылку на tabViewController весь набор вверх. Следующих (последнее), что вам нужно сделать, это действие для кнопки, чтобы перейти к первому (или второму) контроллеру представления, как это:

@IBAction func changeToSecondTab(_ sender: Any) { 
     self.tabViewController?.selectedTabViewItemIndex = 0 // or 1 for second VC 
    } 

Все самое лучшее!

+0

Как чистый код! Спасибо. – 1024jp