简体   繁体   中英

iOS Login Screen Modal on top of Tab Bar or Instantiated

I am developing an iOS App that has several Tabs. So I decided my root view Controller will be a Tab Bar Controller with 2 views. I need the user to login as soon as the application starts, so I'm trying to find out the best approach to do this.

Following other similar questions posted here I've tried this 2 approaches:

  1. Presenting the login screen as a Modal View on top of the Tab Bar Controller

  2. Instantiating the Login view controller

I've done this, by using a UserisLoggedIn flag in NSUserDefaults that is set every time the user logs in or logs out.

The problem I face with both approaches is that before the login screen appears there's a quick flickr of the first view in the Tab Bar. I've tried to resolve this setting the alpha value of the Tab Bar to 0 if the user is not logged in for the modal approach, but for the instance approach it doesnt work, it still flickers before showing the login screen. Anyway, I find this solution tedious and not really elegant.

There must be a standard approach for doing this in iOS, since you have loads of apps that present first a login screen, but since I am a beginner with iOS Programming I still don't know how to do it.

Here's some code from my Tab bar controller:

1st Approach

Tab Bar Controller

 override func viewDidLoad() {
        super.viewDidLoad()
        view.alpha = 0

        let defaults = NSUserDefaults.standardUserDefaults()

        if defaults.objectForKey("userLoggedIn") as NSString == "loggedIn"{
            view.alpha = 1.0
        }

      }


override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(false)
        self.showLoginView()

    }



func showLoginView(){

        let defaults = NSUserDefaults.standardUserDefaults()

        if defaults.objectForKey("userLoggedIn") == nil{
            self.performSegueWithIdentifier("loginView", sender: self)
        }
    }

Login View Controller

func updateUserLoggedInFlag() {
        // Update the NSUserDefaults flag
        let defaults = NSUserDefaults.standardUserDefaults()
        defaults.setObject("loggedIn", forKey: "userLoggedIn")
        defaults.synchronize()
    }

@IBAction func login(sender: AnyObject) {

//Do my login here...
//If login successful:

    self.performSegueWithIdentifier("dismissLogin", sender: self)

}

2nd Approach, Creating an Instance of the Login View Controller

1st View in the Tab Bar

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

        let defaults = NSUserDefaults.standardUserDefaults()
        if defaults.objectForKey("userLoggedIn") == nil{

            let loginController: LoginViewController = self.storyboard?.instantiateViewControllerWithIdentifier("LoginViewController") as LoginViewController
            self.tabBarController?.presentViewController(loginController, animated: false, completion: nil)

}

Login View Controller

@IBAction func login(sender: AnyObject) {

//Do my login here...
    //If login successful:
    self.dismissViewControllerAnimated(true, completion: nil)
}

OK here is what did the trick for me. I don't know if it's the right thing to do, but it seems to work. Like Joseph Duffy mentioned all I did was to set the Login view as the rootviewcontroller in the delegate, and once I was succesfully logged in, switch back to the tab bar controller as rootviewcontroller.

Code in AppDelegate:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let defaults = NSUserDefaults.standardUserDefaults()
            if defaults.objectForKey("userLoggedIn") == nil{         
                showLogin()   
            }

}

 func showLogin() {

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let loginViewController = storyboard.instantiateViewControllerWithIdentifier("LoginViewController") as LoginViewController
        self.window?.makeKeyAndVisible()
        self.window?.rootViewController = loginViewController
 }

Code in LoginViewController

@IBAction func login(sender: AnyObject) {
   //Do my login here...
   //If login successful:
     let storyboard = UIStoryboard(name: "Main", bundle: nil)
     let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
     self.dismissViewControllerAnimated(true, completion: nil)
     appDelegate.window?.rootViewController = storyboard.instantiateViewControllerWithIdentifier("tabBarID") as TabBarController
}

Take a look at a similar question's answer . The solution is to do this check in your app delegate's application:didFinishLaunchingWithOptions: method by checking if the user is logged in and loading the login view from a storyboard when necessary.

I have created a blank project, added a view controller with a storyboard identifier of loginScreen and have the following code in the app delegate:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    self.showLogin()

    return true
}

func showLogin() {
    //loginScreen
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let loginViewController = storyboard.instantiateViewControllerWithIdentifier("loginScreen") as UIViewController
    if let window = self.window {
        window.makeKeyAndVisible()
        window.rootViewController?.presentViewController(loginViewController, animated: false, completion: nil)
    }
}

This shows the login screen and the main screen is not seen.

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

         let defaults = NSUserDefaults.standardUserDefaults()
          if defaults.objectForKey("userLoggedIn") == nil{

          showLoginView()

   }

func showLoginView(){

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let loginViewController: LoginViewController = storyboard.instantiateViewControllerWithIdentifier("LoginViewController") as LoginViewController
        self.window?.makeKeyAndVisible()
        self.window?.rootViewController?.presentViewController(loginViewController, animated: true, completion: nil)
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM