无法切换到容器视图中的另一个子视图控制器

Cannot switch to another child view controller in container view

我有一个主视图控制器、一个容器视图和 2 个子视图控制器,我希望能够在子视图控制器之间切换(例如:当应用程序第一次加载时,我希望包含要加载的 MapView 的控制器,当我按下主视图中的搜索栏时,将加载带有 table 的控制器)。 这是我的故事板:https://i.stack.imgur.com/rDPMe.png

MainScreen.swift

class MainScreen: UIViewController {

@IBOutlet private weak var searchBar: UISearchBar!
@IBOutlet private weak var ContainerView: UIView!
//private var openSearchBar: Bool?
private var openMapView: Bool = true
private var openPlacesList: Bool = false
private var containerView: ContainerViewController!

override func viewDidLoad() {
    super.viewDidLoad()
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    //let containerView = segue.destination as? ContainerViewController
    if containerView == nil{
        containerView = segue.destination as? ContainerViewController
    }
    if openMapView == true{
        containerView!.moveToMapView()
    }
    else if openPlacesList == true{
        containerView!.MoveToOpenPlaces()
    }
  }
}
//search bar delegate functions
extension MainScreen: UISearchBarDelegate{
//detects when text is entered
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    openPlacesList = true
    openMapView = false
    containerView!.MoveToOpenPlaces()
  }
}

ContainerViewController.swift:

class ContainerViewController: UIViewController {

private var childViewController: UIViewController!

private var first: UIViewController?
private var sec: UIViewController?

override func viewDidLoad() {
    super.viewDidLoad()
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "MainToMap"{

        first = segue.destination as! MapViewController
        self.addChild(first!)
        self.view.addSubview(first!.view)
        self.didMove(toParent: self)
    }else{
       sec = segue.destination as! PlacesListController
    }

    if(first != nil && sec != nil){
        interchange(first!,sec!)
    }
}

func interchange(_ oldVc: UIViewController,_ newVc: UIViewController ){
    oldVc.willMove(toParent: nil)
    self.addChild(newVc)
    self.view.addSubview(newVc.view)

    self.transition(from: oldVc, to: newVc, duration: 2, options: UIView.AnimationOptions.transitionCrossDissolve, animations: {
        newVc.view.alpha = 1
        oldVc.view.alpha = 0
    }, completion: { (complete) in
        oldVc.view.removeFromSuperview()
        oldVc.removeFromParent()
        newVc.willMove(toParent: self)
    })
}

func moveToMapView(){
    performSegue(withIdentifier: "MainToMap", sender: nil)
}

func MoveToOpenPlaces(){
    performSegue(withIdentifier: "MainToSearches", sender: nil)
}

}

问题是当我按下搜索栏时,它调用了方法交换,然后它只给出了一个 SIGABRT 1 错误。我尝试了本教程:https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html#//apple_ref/doc/uid/TP40007457-CH11-SW1 等等,但到目前为止还没有成功。我被困在这里,不知道如何解决这个问题。

堆栈:https://i.stack.imgur.com/Zqpm1.png SIGABR 1 错误:https://i.stack.imgur.com/NBgEN.png

您似乎在尝试在子视图控制器之间手动转换,但同时使用 segues(它们会为您进行自己的转换)。消除转场(初始嵌入转场除外,如果您使用带有 "container view" 的故事板),只需使用故事板 ID 手动实例化子视图控制器。但是不要使用 segues 然后尝试替换 prepare(for:sender:).

中的子视图控制器

此外,当您使用 transition(from:to:duration:options:animations:completion:), you should not add the views the the view hierarchy yourself. That method does that for you (unless you use the showHideTransitionViews option, which tells the method that you're taking this over, something we don't need to do here). Likewise, when you use the transitionCrossDissolve 选项时,您也不需要弄乱字母。


因此,使用您引用的那篇文章中的代码片段,您可以:

class FirstViewController: UIViewController {

    @IBOutlet weak var containerView: UIView!  // the view for the storyboard's "container view"
    @IBOutlet weak var redButton: UIButton!    // a button to transition to the "red" child view controller
    @IBOutlet weak var blueButton: UIButton!   // a button to transition to the "blue" child view controller

    // tapped on "transition to red child view controller" button

    @IBAction func didTapRedButton(_ sender: UIButton) {
        redButton.isEnabled = false
        blueButton.isEnabled = true

        let oldVC = children.first!
        let newVC = storyboard!.instantiateViewController(withIdentifier: "RedStoryboardID")
        cycle(from: oldVC, to: newVC)
    }

    // tapped on "transition to blue child view controller" button

    @IBAction func didTapBlueButton(_ sender: UIButton) {
        blueButton.isEnabled = false
        redButton.isEnabled = true

        let oldVC = children.first!
        let newVC = storyboard!.instantiateViewController(withIdentifier: "BlueStoryboardID")
        cycle(from: oldVC, to: newVC)
    }

    func cycle(from oldVC: UIViewController, to newVC: UIViewController) {
        // Prepare the two view controllers for the change.
        oldVC.willMove(toParent: nil)
        addChild(newVC)

        // Get the final frame of the new view controller.
        newVC.view.frame = containerView.bounds

        // Queue up the transition animation.
        transition(from: oldVC, to: newVC, duration: 0.25, options: .transitionCrossDissolve, animations: {
            // this is intentionally blank; transitionCrossDissolve will do the work for us
        }, completion: { finished in
            oldVC.removeFromParent()
            newVC.didMove(toParent: self)
        })
    }

    func display(_ child: UIViewController) {
        addChild(child)
        child.view.frame = containerView.bounds
        containerView.addSubview(child.view)
        child.didMove(toParent: self)
    }

    func hide(_ child: UIViewController) {
        child.willMove(toParent: nil)
        child.view.removeFromSuperview()
        child.removeFromParent()
    }

}

产生: