1

I'm setting my window's root view controller as the login controller right off the bat, and the login controller checks user authentication from Firebase. If the user is logged in, the controller changes the root view controller to be the feed controller. Otherwise, the login controller proceeds as itself.

class LoginController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        if let uid = Auth.auth().currentUser?.uid {

            Database.database().reference().child("users").observeSingleEvent(of: .value, with: { snapshot in
                if snapshot.hasChild(uid) {
                    AppDelegate.launchApplication()
                }
                else {
                    self.setUpUI()
                }
            })

        }
        else {
            self.setUpUI()
        }

    }
...
}

where launchApplication is

class func launchApplication() {
    guard let window = UIApplication.shared.keyWindow else { return }
    window.rootViewController = UINavigationController(rootViewController: FeedController())
}

In addition to if let uid = Auth.auth().currentUser?.uid, I'm checking whether the uid (if it isn't nil) exists in my database, because I have had the situation where a deleted user still wasn't nil.

The problem is that after the launch screen finishes, there is a moment when the login controller, though blank, is visible. Sometimes this moment lasts a few seconds. How can I check authentication such that the login controller isn't visible at all—so that the app decides how to proceed immediately after the launch screen disappears? Thanks.

Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
Archie Gertsman
  • 1,601
  • 2
  • 17
  • 45
  • did you just tried presenting from Appdelegate ? it is happening because firstly you are initialising loginController this is why residue is being displayed – iOS Geek Jul 26 '17 at 03:35

3 Answers3

0

As a quick fix, you could try checking just the desired "users" child node (and not the complete branch). For instance:

Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { snapshot in
    if snapshot.exists() { ...

This could reduce your delay considerably if your database contains many users.

If that isn't enough, you might consider moving this logic to you AppDelegate class as well and show your LoginController from there (and maybe holding off your launch screen a little longer until you find out if an user is available).

Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
  • @ArchieGertsman Actually you are checking *just* a single user in your original code: `snapshot.hasChild(uid)`. This should work fine, but might not scale well since you are unnecessarily downloading the *complete* `users` branch as well ;) – Paulo Mattos Jul 29 '17 at 16:17
0

1) use this following code in case if you want to set a rootController from app delegate itself . use a check if your currentUser.uid is not nil and matched with values in database then perform following code in DidFinishLaunchingWithOptions of Appdelegate . Used by me

            func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    FirebaseApp.configure()
    GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID



    if let uid = Auth.auth().currentUser?.uid {

        Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value, with: { snapshot in
            if snapshot.exist() {
                let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
                let vc = storyBoard.instantiateViewController(withIdentifier: "feedController") as! FeedController

                self.window?.rootViewController=vc
                self.window?.makeKeyAndVisible()
            }
            else {
                //Present your loginController here
            }
        })

    }

    return true
}

2) Method: when you had initialised your logincontroller instead of calling a function from Appdelegate or code in LaunchApplication. make a function in login class and write the following code when required parameters are matched

 var transition: UIViewAnimationOptions = .transitionFlipFromLeft
let rootviewcontroller: UIWindow = ((UIApplication.shared.delegate?.window)!)!
        rootviewcontroller.rootViewController = self.storyboard?.instantiateViewController(withIdentifier: "rootnav")//rootnav is Storyboard id of my naviagtionController attached to the DestinationController [FeedController]
        let mainwindow = (UIApplication.shared.delegate?.window!)!
        mainwindow.backgroundColor = UIColor(hue: 0.6477, saturation: 0.6314, brightness: 0.6077, alpha: 0.8)
        UIView.transition(with: mainwindow, duration: 0.55001, options: transition, animations: { () -> Void in
        }) { (finished) -> Void in

        }
iOS Geek
  • 4,825
  • 1
  • 9
  • 30
  • You're probably going to want to remove the setting for the default view: in the attributes inspector, there's a checkbox for *Is Initial View Controller*. Uncheck that so you can determine the view in code. – Jay Jul 26 '17 at 16:30
0

Instead of changing any code, I simply set the background of the login controller to match the launch screen:

class LoginController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // here
        let background_image_view = UIImageView(image: #imageLiteral(resourceName: "launch_screen_background"))
        background_image_view.frame = self.view.frame
        self.view.addSubview(background_image_view)

        if let uid = Auth.auth().currentUser?.uid {

            Database.database().reference().child("users").observeSingleEvent(of: .value, with: { snapshot in
                if snapshot.hasChild(uid) {
                    AppDelegate.launchApplication()
                }
                else {
                    self.setUpUI()
                }
            })

        }
        else {
            self.setUpUI()
        }

    }
...
}

There is no noticeable transition from the launch screen to the login controller.

Archie Gertsman
  • 1,601
  • 2
  • 17
  • 45