本文介绍了无法在容器视图中切换到另一个子视图控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个主视图控制器、一个容器视图和 2 个子视图控制器,我希望能够在子视图控制器之间切换(例如:当应用程序第一次加载时,我希望控制器包含要加载的 MapView,当我按下在主视图中找到的搜索栏时,带有要加载的表格的控制器).这是我的故事板:

I have a main view controller, a container view and 2 child view controllers and i would like to be able to switch between the children (for example: when the application loads for the first time, i would like that the controller containing the MapView to be loaded and when i press the Search Bar found in the main view, the controller with the table to be loaded).Here is my storyboard: 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)
}

}

The problem is that when I press the search bar, it calls the method interchange and then it just gives a SIGABRT 1 error. I tried this tutorial: https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html#//apple_ref/doc/uid/TP40007457-CH11-SW1 and many more but so far no luck. I am stucked here and don't know how i can solve this problem.

Stack: https://i.stack.imgur.com/Zqpm1.pngSIGABR 1 Error: https://i.stack.imgur.com/NBgEN.png

解决方案

You appear to be trying to manually transition between child view controllers, but at the same time using segues (which do their own transitioning for you). Eliminate the segues (other than the initial embed segue, if you're using a storyboard with a "container view"), and just manually instantiate the child view controllers using their storyboard IDs. But don't use segues and then try to replace the child view controllers in prepare(for:sender:).

Also, when you use 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 option, you don't need to mess with alphas, either.


Thus, using the code snippet from that article you reference, you can do:

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()
    }

}

That yields:

这篇关于无法在容器视图中切换到另一个子视图控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 08:09