Search code examples
iosswiftfacebook-ios-sdk

How to correctly get the top most view controller and cast it


Hi I have this navigation stack:

NavigationController-->ViewController-->With subsequent VCs

In the top most VC, I have an activity indicator that I am turning on when the user clicks "Login with Facebook" and then wanting to turn off in the closure of FBRequestConnection. FBRequestConnection is asynchronous so this needs to be turned off from within the closure.

The following method is not called from within the LoginVC itself, so I need to get it off the navigation stack. I have tried:

if let loginVC = UIApplication.sharedApplication().keyWindow?.rootViewController?.navigationController?.visibleViewController? as? LoginVC {
                    loginVC.turnOffActivityIndictator()
                }

and also:

if let loginVC = UIApplication.sharedApplication().delegate?.window??.rootViewController as? LoginVC {
                    loginVC.turnOffActivityIndictator()
                }

But it is not working. I have also tried other suggestions but am unable to find a solution. How do I get around this, or has anyone else got any better ideas?

The variable window in XCode seems to look like it is all ok but the if let statement just skips over the trailing {} which means that the as? is failing if I am correct?

enter image description here

Here is the (incomplete) method:

private class func makeRequestForUserData() -> Void {
    var dict = NSMutableDictionary()
    FBRequestConnection.startForMeWithCompletionHandler({(connection, result, error) -> Void in
        if (error == nil) {
            // Success! Include your code to handle the results here
            let resultDict = result as [String:AnyObject]
            if let usersEmail = resultDict["email"] as? String {
                if DBUser.loginUserForEmail(usersEmail) == true {
                    //Go to main menu
                }else {
                    // no user exists.. alert message
                    // take then to sign up page
                }
            }else{
                // error got nothing from the result dict!!
            }
            if let loginVC = UIApplication.sharedApplication().keyWindow?.rootViewController?.navigationController?.visibleViewController? as? LoginVC {
                loginVC.turnOffActivityIndictator()
            }
        } else {
            // An error occurred, we need to handle the error
            // Check out our error handling guide: https://developers.facebook.com/docs/ios/errors/
            FBErrorHandler.processError(error)
        }
    })
}

Solution

  • NavigationController-->ViewController-->With subsequent VCs

    From this navigation stack your rootViewController does not have navigationController but it is navigationController itself so UIApplication.sharedApplication().keyWindow?.rootViewController?.navigationController? is returning nil I think. Try casting rootViewController to UINavigationController then get it's viewControllers, then get the desired viewController

    if let viewControllers = (UIApplication.sharedApplication().keyWindow?.rootViewController? as UINavigationController).viewControllers {
    
        //get first controller in hierarchy    
        if let loginVC = viewControllers[0] as? LoginVC{
    
            loginVC.turnOffActivityIndictator()
        }       
    }