30

I make walkthrough (onboarding flow) in my app and I'd like to have a skip button. The button is located on viewController, so I figured out that the best way to move to another viewController would be access app delegate window.

However, it keeps getting me an error that AppDelegate.Type does not have a member called "window".

@IBAction func skipWalkthrough(sender: AnyObject) {
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    AppDelegate.window!.rootViewController = RootViewController   
}

Is there anything wrong with such approach?

Thanks in advance!

theDC
  • 6,364
  • 10
  • 56
  • 98

8 Answers8

57

You have a typo it is supposed to be appDelegate not AppDelegate. So like this:

@IBAction func skipWalkthrough(sender: AnyObject) {
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    appDelegate.window!.rootViewController = RootViewController   
}

Swift 3.2

@IBAction func skipWalkthrough(_ sender: AnyObject) {
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.window!.rootViewController = controller
    }
OurangZeb Khan
  • 1,114
  • 18
  • 20
Stefan Salatic
  • 4,513
  • 3
  • 22
  • 30
  • Ok right, what a studip mistake! Btw, now there is a problem with RootViewController, how to access this view controller which is declared in storyboard? I guess making a new instance isn't a good idea? I mean RootViewController() leads to black screen, so should be another wait to access such controller – theDC May 04 '15 at 10:36
  • Here is how I do it in my code `let storyboardId = "LoginStoryboardIdentifier"` `self.window?.rootViewController = self.window?.rootViewController?.storyboard?.instantiateViewControllerWithIdentifier(storyboardId) as? UIViewController` – Stefan Salatic May 04 '15 at 10:49
  • Works perfectly but while noticing memory consumption, I see no memory decrease when I replace the Root View controller (a) with (b). It means (a) has not wiped out from the memory, right? How to wipe it out from memory 1st and then show (b) controller – Talha Ahmad Khan Dec 28 '17 at 04:57
20

This is for with or without Storyboard and it is working for Swift 3+

let appDelegate = UIApplication.shared.delegate as? AppDelegate
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let homeController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
appDelegate?.window?.rootViewController = homeController
Roman Podymov
  • 4,168
  • 4
  • 30
  • 57
Dasoga
  • 5,489
  • 4
  • 33
  • 40
  • 2
    Does this still work in Swift 5+, I can't seem to get this to work, the line appDelegate?.window throws an error saying cannot use optional chaining on non-optional value of type 'any', fixing it gives other errors. – Joseph Astrahan Feb 05 '20 at 23:30
11

Swift 3

This is a better way:

    if let window = NSApplication.shared().windows.first {
        window.acceptsMouseMovedEvents = true;
    }
Ted Lowery
  • 1,535
  • 2
  • 13
  • 8
9

appDelegate.window!.rootViewController is not working in Swift 5

Here is working code

Add below extension

extension UIWindow {
    static var key: UIWindow! {
        if #available(iOS 13, *) {
            return UIApplication.shared.windows.first { $0.isKeyWindow }
        } else {
            return UIApplication.shared.keyWindow
        }
    }
}

use

let mainSB = UIStoryboard(name: "Main", bundle: nil)
                    
if let RootVc = mainSB.instantiateViewController(withIdentifier: "NavigationController") as? UINavigationController{
    UIWindow.key.rootViewController = RootVc
}

UIWindow.key // to access only window
Nikunj Kumbhani
  • 3,758
  • 2
  • 26
  • 51
  • 1
    This is how you access instance of UIWindow in Swift5 , iOS 13 & above versions to set it's rootViewController or to present any UIView. Thanks mate. – Suhail Sep 06 '20 at 15:48
  • @Suhail I forgot 1 line to Add **window.makeKeyAndVisible()** Please check my Updated Answer it will sure work :) – Nikunj Kumbhani Sep 07 '20 at 05:21
5

You can also use conditional binding to reach the window.

if let window = UIApplication.shared.windows.first {
    // use window here.
}
Gustavo Vollbrecht
  • 3,188
  • 2
  • 19
  • 37
2

You are using the protocol name (i.e. AppDelegate) instead of the instance:

Should be:

appDelegate.window!.rootViewController = RootViewController   
giorashc
  • 13,691
  • 3
  • 35
  • 71
2

You can access tab bar anywhere from the app. Use below:

let appDelegate = UIApplication.shared.delegate as! AppDelegate

if let tabBarController = appDelegate.window!.rootViewController as? UITabBarController {
    if let tabItems = tabBarController.tabBar.items {
       let tabItem = tabItems[2]
       tabItem.badgeValue = "5" //enter any value
    }
}
Umit Kaya
  • 5,771
  • 3
  • 38
  • 52
1

This solution work for : After Login / Register Programmatically add UITabbarController

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController = tabs
appDelegate.window!.makeKeyAndVisible()
iGatiTech
  • 2,306
  • 1
  • 21
  • 45
Humza Shahid
  • 33
  • 11
  • Whilst this code snippet is welcome, and may provide some help, it would be [greatly improved if it included an explanation](//meta.stackexchange.com/q/114762) of *how* and *why* this solves the problem. Remember that you are answering the question for readers in the future, not just the person asking now! Please [edit] your answer to add explanation, and give an indication of what limitations and assumptions apply. – Toby Speight Feb 16 '17 at 13:28