简体   繁体   English

使用Swift和iOS 8 Storyboard登录屏幕

[英]Login Screen with Swift and iOS 8 Storyboard

I have having a lot of trouble handling the login flow of my iOS app. 我在处理iOS应用程序的登录流程时遇到了很多麻烦。 An image of the storyboard I am trying to achieve is below 我想要实现的故事板的图像如下

在此输入图像描述

I am trying to achieve an optional login screen which is presented only when a user first opens the app and has not logged in. Currently, I have the Tab Bar Controller set as the root view controller. 我正在尝试实现一个可选的登录屏幕,该屏幕仅在用户首次打开应用程序并且尚未登录时显示。目前,我将Tab Bar Controller设置为根视图控制器。 I can not figure out how to handle swapping between these view controllers, however. 但是,我无法弄清楚如何处理这些视图控制器之间的交换。

I have tried to simply push the login screen with the following code. 我试图用以下代码简单地按下登录屏幕。 However, it does not work. 但是,它不起作用。 I believe the problem that a tab bar controller is not allowed to push new view controllers. 我相信标签栏控制器不允许推送新视图控制器的问题。

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

    if userLoggedIn {
        // Do nothing
    } else {
        //get access to login view
        var storyboard = UIStoryboard(name: "Main", bundle: nil)
        var viewController =    storyboard.instantiateViewControllerWithIdentifier("signupView") as UIViewController;

        // Then push login view
        var rootViewController = self.window!.rootViewController as UITabBarController;
        rootViewController.pushViewController(viewController, animated: true)
    }

    // Override point for customization after application launch.
    return true
}

Is there a way to switch view controllers without pushing within a navigation controller? 有没有办法在不推入导航控制器的情况下切换视图控制器? Any advice on how to handle this sort of login flow would be greatly appreciated. 任何关于如何处理这种登录流程的建议将不胜感激。

I achieve this with a "LaunchViewController" that determines if it should present the Login view or the main navigation controller. 我通过“LaunchViewController”来实现这个目的,它确定它是否应该呈现Login视图或主导航控制器。

Mark the launch view your initial view in the storyboard and write the logic in there to determine which to present. 将启动视图标记为故事板中的初始视图,并在其中编写逻辑以确定要呈现的内容。 This process is often very quick and unnoticeable to the user. 对于用户来说,该过程通常非常快速且不明显。

UPDATE : 更新

As mentioned in my comment I've gone a different direction. 正如我在评论中所提到的,我走的是另一个方向。 Now in the App Delegate's application(application:didFinishLaunchingWithOptions:) method I perform the logic necessary to determine which view should be the rootViewController and set it there using the following. 现在在App Delegate的application(application:didFinishLaunchingWithOptions:)方法中,我执行必要的逻辑来确定哪个视图应该是rootViewController并使用以下内容将其设置在那里。

extension AppDelegate {

    enum LaunchViewController {
        case Login, Dashboard

        var viewController: UIViewController {
            switch self {
            case .Login: return StoryboardScene.Login.LoginScene.viewController()
            case .Dashboard: return StoryboardScene.Dashboard.initialViewController()
            }
        }

        /// Sets `UIWindow().rootViewController` to the appropriate view controller, by default this runs without an animation.
        func setAsRootviewController(animated animated: Bool = false) {
            let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
            let window = appDelegate.window!
            let launchViewController = viewController

            log.info?.message("Setting \(launchViewController.dynamicType) as rootViewController")
            if let rootViewController = window.rootViewController where rootViewController.dynamicType != launchViewController.dynamicType && animated {
                let overlayView = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(false)
                launchViewController.view.addSubview(overlayView)

                UIView.animateWithDuration(0.3, animations: {
                    overlayView.alpha = 0.0
                    },
                    completion: { _ in
                        overlayView.removeFromSuperview()
                });
            }

            window.rootViewController = launchViewController
            window.restorationIdentifier = String(launchViewController.dynamicType)

            if window.keyWindow == false {
                window.makeKeyAndVisible()
            }
        }
    }
}

Note that StoryboardScene is not a default type, I am using https://github.com/AliSoftware/SwiftGen to generate that. 请注意, StoryboardScene不是默认类型,我使用https://github.com/AliSoftware/SwiftGen来生成它。

My App Delegate method looks something like this. My App Delegate方法看起来像这样。

if window == nil {
    window = UIWindow(frame: UIScreen.mainScreen().bounds)
}

if isRestoringState == false {
    if let _ = lastUsedAccount {
        LaunchViewController.Dashboard.setAsRootviewController()
    } else {
        LaunchViewController.Login.setAsRootviewController()
    }
}

UPDATE with Logout method for Comment 使用Logout方法更新注释

func handleLogout(notification: NSNotification) {
  LaunchViewController.Login.setAsRootviewController(animated: true)
  lastUsedAccount = nil
}

Here is what i did and it works fine : 这是我做的,它工作正常:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    if (!AppData.sharedInstance.loggedIn) {
        let signInNavigation = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("SignInNavigationControllerIdentifier") as? UINavigationController
        self.window!.rootViewController = signInNavigation;
    }
    return true
}

Set Is Initial View Controller for LoginViewController. 为LoginViewController设置Is Initial View Controller

在此输入图像描述

Remove from AppDelegate.swift and place it in LoginViewController . AppDelegate.swift删除并将其放在LoginViewController

if userLoggedIn {
        // Do nothing
    } else {
        //get access to login view
        var storyboard = UIStoryboard(name: "Main", bundle: nil)
        var viewController =    storyboard.instantiateViewControllerWithIdentifier("signupView") as UIViewController;

        // Then push login view
        var rootViewController = self.window!.rootViewController as UITabBarController;
        rootViewController.pushViewController(viewController, animated: true)
    }

Run your project. 运行您的项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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