I'm trying to navigate view controllers using a segmented controller. The child VC gets attached to the parent and I can switch VC's this way. However, every time I go back to a segment the VC gets reinstated all over again. How can I make the VC attach itself again if it's already loaded into memory?
Here is my code and how I'm trying to check if a view is loaded.
@objc func changeView1(_ kMIDIMessageSendErr: Any?) {
let childViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "View1")
if childViewController.isViewLoaded == true {
childViewController.didMove(toParentViewController: self)
NSLog("ViewIsLoaded1")
} else if childViewController.isViewLoaded == false {
self.addChildViewController(childViewController)
self.view.addSubview(childViewController.view)
childViewController.didMove(toParentViewController: self)
NSLog("ViewIsLoaded2")
}
}
@objc func changeView2(_ kMIDIMessageSendErr: Any?) {
let childViewController2 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "View2")
if childViewController2.isViewLoaded == true {
childViewController2.didMove(toParentViewController: self)
NSLog("ViewIsLoaded3")
} else if childViewController2.isViewLoaded == false {
self.addChildViewController(childViewController2)
self.view.addSubview(childViewController2.view)
childViewController2.didMove(toParentViewController: self)
NSLog("ViewIsLoaded4")
}
}
I am able to change VC's using the segmented control, but I don't want to reload the VC every time I change segments.
There are a number of problems with your code:
1) You're creating a brand new instance of your child controller every time either of these functions is run. Therefore isViewLoaded
is always false, and the execution flows into your else
block every single time.
2) The else if
is not required.
3) Providing the above are solved, you shouldn't be calling didMove(toParentViewController:)
to switch back. You should simply be hiding and unhiding the views.
The solutions to this are as follows:
1) Assign a reference to your child controllers as an instance variable, and create a child only if that reference is nil.
2) Instead of checking isViewLoaded
, check your instance variable reference to see if it is nil.
3) Remove the if
part of your else
clause - it's redundant.
4) Inside your if
code block, simply hide and unhide the appropriate views using isHidden
.
Here's an example implementation:
private var firstChild: UIViewController?
private var secondChild: UIViewController?
@objc func changeView1(_ kMIDIMessageSendErr: Any?) {
if firstChild != nil {
firstChild?.view.isHidden = false
secondChild?.view.isHidden = true
} else {
firstChild = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "View1")
self.addChildViewController(firstChild!)
self.view.addSubview(firstChild!.view)
firstChild!.didMove(toParentViewController: self)
}
}
@objc func changeView2(_ kMIDIMessageSendErr: Any?) {
if secondChild != nil {
firstChild?.view.isHidden = true
secondChild?.view.isHidden = false
} else {
secondChild = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "View2")
self.addChildViewController(secondChild!)
self.view.addSubview(secondChild!.view)
secondChild!.didMove(toParentViewController: self)
}
}