iosswiftuiviewcontrollerhierarchyparseui

Present *.viewController on PFLogInViewController whose view is not in the window hierarchy


I have already looked on StackOverFlow. No existing questions seem to help me.

I am using ParseUI to handle user login functionality but am running into problems when signing new users up.

Problem: When a user goes to sign up and hits the "Sign Up" button, this error appears and no segue happens:

<Warning: Attempt to present edus.ClassEntryViewController: 0x7f8800ceb0a0> on <PFLogInViewController: 0x7f8800c2f520> whose view is not in the window hierarchy!

I do not know how to fix this. Relevant code below:

import UIKit
import Parse
import Bolts
import ParseUI
import FBSDKCoreKit
import ParseFacebookUtils


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
var parseLoginHelper: ParseLoginHelper!

override init() {
    super.init()

    parseLoginHelper = ParseLoginHelper {[unowned self] user, error in
        // Initialize the ParseLoginHelper with a callback
        if let error = error {
            // 1
            ErrorHandling.defaultErrorHandler(error)
        } else  if let user = user {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            //creation
            let classNavEntry = storyboard.instantiateViewControllerWithIdentifier("ClassNavEntry") as! UIViewController
            //presentation. PROBLEM HERE??
            self.window?.rootViewController!.presentViewController(classNavEntry, animated:true, completion:nil)
        }
    }
}

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let user = PFUser.currentUser()

    let startViewController: UIViewController;

    if (user != nil) {
        // 3
        // if we have a user, set the ClassNavEntry to be the initial View Controller
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        //problem may arise here
        startViewController =
                storyboard.instantiateViewControllerWithIdentifier("ClassNavEntry") as! UINavigationController
    } else {
        // 4
        // Otherwise set the LoginViewController to be the first
        let loginViewController = PFLogInViewController()
        loginViewController.fields = .UsernameAndPassword | .LogInButton | .SignUpButton | .PasswordForgotten | .Facebook
        loginViewController.delegate = parseLoginHelper
        loginViewController.signUpController?.delegate = parseLoginHelper
        startViewController = loginViewController
    }

    // 5
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    self.window?.rootViewController = startViewController;
    self.window?.makeKeyAndVisible()

UPDATE: I know what is causing the problem, still figuring out how to fix it.

The problem is that there are two view controllers: loginViewController and SignupViewController. I specify that the root view controller is the loginViewController here:

loginViewController.delegate = parseLoginHelper
        loginViewController.signUpController?.delegate = parseLoginHelper
        startViewController = loginViewController
    }

    // 5
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    //THIS SPECIFIES ROOTVIEW TO BE LOGINVIEWCONTROLLER
    self.window?.rootViewController = startViewController
    self.window?.makeKeyAndVisible()

So I need to be able to call the parseHelper on the SignUpViewController as well...


Solution

  • Add this line of code on your ParseLoginHelper inside the function that reacts for a new Sign Up (didSignUpUser)

    signUpController.dismissViewControllerAnimated(true, completion: nil)
    

    It should look like this:

    extension ParseLoginHelper : PFSignUpViewControllerDelegate {
      func signUpViewController(signUpController: PFSignUpViewController, didSignUpUser user: PFUser) {
        signUpController.dismissViewControllerAnimated(true, completion: nil)
        self.callback(user, nil)
      } 
    }