1

Struggling a couple of days with this...

I have set a rootVC from AppDelegate in didFinishLaunchingWithOptions and this is working fine.

Now from that rootVC I want that, if some condition is met, eg. if x=y a new rootVC is set and displayed.

I stack overflowed long long time, found different solutions, but none is working.

The below is compiling, and executing, I checked with breakpoint, but nothing shows up in the app.

animated    Bool    false   
self    Regional2.IrelandViewController 0x0000000102b0ff30
newViewController   Regional2.IrelandMain   0x0000000102d0d300
customViewControllersArray  NSArray 0x00000001c000b620
ObjectiveC.NSObject NSObject    
Exception State Registers       
far unsigned long   0x00000001b0a7ba78
esr unsigned int    0x92000007
exception   unsigned int    0x00000000
Floating Point Registers        
General Purpose Registers       

and the piece of the code . . .

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    let newViewController = self.storyboard?.instantiateViewController(withIdentifier: "IrelandMain") as! IrelandMain

    let customViewControllersArray : NSArray = [newViewController]

    self.navigationController?.viewControllers = customViewControllersArray as! [UIViewController]
    self.navigationController?.pushViewController(newViewController, animated: true)

}

Please notice that navigationController show produces the same output. Nothing changes.

koen
  • 5,383
  • 7
  • 50
  • 89
czane
  • 392
  • 1
  • 6
  • 18
  • Why do you need to remove the existing root VC and replace it with a different one rather than have the navigation controller push the new VC on top of the existing one? If you really need to replace one VC with another make sure `newViewController` is not `nil`. Check the `navigationController` too. Is the original root VC a navigation controller? If both those things are non-nil try commenting out the two lines with `customViewControllersArray` in them and see what happens then. – theMikeSwan Dec 05 '17 at 18:48

1 Answers1

0

That code works for me. It simply replaces the whole UIWindow.

When I tried to only replace the rootViewController it did it but it created another one (so I had two loaded viewControllers in the view hierarchy)

if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
    // If we only reloads the rootViewController than the main window has 2 subviews
    // The older cannot be removed and the new can be removed.
    // The workaround I found is to replace the whole UIWindow with new one
    let root = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateInitialViewController()
    let newWindow = UIWindow()
    appDelegate.replaceWindow(newWindow)
    newWindow.rootViewController = root
}

And in your AppDelegate

func replaceWindow(_ newWindow: UIWindow) {
    if let oldWindow = window {
        newWindow.frame = oldWindow.frame
        newWindow.windowLevel = oldWindow.windowLevel
        newWindow.screen = oldWindow.screen
        newWindow.isHidden = false
        window = newWindow
        oldWindow.removeFromSuperview()
    }
}
Yitzchak
  • 3,303
  • 3
  • 30
  • 50
  • This solution works for me! Thank you. You said "I had two loaded viewControllers in the view hierarchy" , where I can check that in Xcode9 ? – czane Dec 07 '17 at 15:57
  • 1
    In the debug pane there is a button that let you see the view hierarchy in 3D, very useful. See this: https://stackoverflow.com/questions/5150186/how-do-i-inspect-the-view-hierarchy-in-ios – Yitzchak Dec 07 '17 at 18:09