我如何在viewcontroller中远离关闭?

时间:2017-08-27 07:32:39

标签: swift firebase viewcontroller

尝试找一些关于它的信息,但我不能。

所以当我点击登录时,我得到了这段代码。

@IBAction func checkLogin(_ sender: UIButton) {

    let email = userEmail.text!
    let password = userPassword.text!

    if email == "" || password == "" || !email.isValidEMail {
        userEmail.shake()
        userPassword.shake()
        return
    }

    Auth.auth().signIn(withEmail: email, password: password, completion: {(user, error) in

        var collectError = ("","")

        if error != nil {
            collectError = ("Error", (error?.localizedDescription)!)
            self.alertMsg(title: collectError.0, message: collectError.1)
            return
        }

        if !(user?.isEmailVerified)! {
            collectError = ("Error", "Your account is not verified! Confirm your account from email!")
            return
        }

        print("OK, User Authentificated: \(Auth.auth().currentUser?.email)")

        // DispatchQueue.main.async { }
        //return

        self.navigationController?.popViewController(animated: true)
        //self.dismiss(animated: true, completion: nil)

    })

我有第一个视图控制器,它为用户提供登录或注册选项。所以我选择登录。尝试登录,它返回到第一个视图控制器那里我有验证firebase监听器,如果用户loggen隐藏第一个视图控制器,但当我点击登出profile.storyboard它立即显示我第一个登录控制器。当我再次尝试再次登录时,为什么我不知道

据我所知,我需要用于导航返回功能

self.navigationController?.popViewController(animated: true)

和按钮,如果我想隐藏viewcontrol

self.dismiss(animated: true, completion: nil)

1 个答案:

答案 0 :(得分:0)

因此,当你的main.storyboard的根控制器被加载或将要/确实出现时,你正试图检查授权,如果用户未经授权,你将出示登录控制器,对吗?

在你的情况下,你需要至少有两个独立的导航堆栈(让我们称之为主堆栈和登录堆栈)

这意味着在用户未成功登录或解除注册后取消(未弹出)用户时,应显示(未推送)您的登录视图控制器。

我的项目中有几乎相同的reg过程。我将尝试在下面的示例代码中解释它

class MainController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        //detecting the firebase, just a custom bool var
        if !isAuthorized {
            //call the method to present login controller
            presentLoginController()
        }
    }

    func presentLoginController(){
        let segue = UIStoryboard(name: "Login", bundle: nil)

        if let loginNavigationController = segue.instantiateInitialViewController() {

            self.present(loginNavigationController, animated: true, completion: nil)
        }

    }


}

现在您将看到登录控制器。所以这将构成第二个导航堆栈(登录堆栈)。这将是一个单独的导航,其中根控制器是登录导航控制器(Login.storyboard中的初始控制器)。对于此堆栈中的任何控制器,如果您将调用navigationController?.popToRootViewController,它将带您到登录堆栈中的根控制器。不要在这里使用self.dismiss(animated:true,completion:nil),这可能会破坏你的导航

因此,当用户登录或授权完成或取消时,您需要显示一个主控制器(主堆栈),您可以在其中再次检查isAuthorized。这就是你如何做到的:

func navigateToTheRoot(){
        //this code will dismiss all modal controllers that was presented
        UIApplication.shared.keyWindow?.rootViewController?.dismiss(animated: false, completion: nil)

        //accessing to the appDelegate
        let appDelegate = UIApplication.shared.delegate as? AppDelegate

        //now this will return your app to the main controller
        if let navigationController = appDelegate?.window?.rootViewController as? UINavigationController {
            navigationController.popToRootViewController(animated: true)
        }
 }

在分离的导航堆栈中显示的任何控制器中调用此方法(如取消注册,在单击登录堆栈中的“X”按钮后调用此方法)。

如果您的配置文件控制器有一个导航控制器作为Profile.storyboard的初始值(第三个堆栈 - 配置文件堆栈),那么您需要以与我用于登录控制器相同的方式呈现它。在这种情况下,要进行注销,需要从配置文件堆栈中的任何控制器调用方法navigateToTheRoot()来显示主控制器。

否则,如果您的配置文件控制器只是一个没有额外导航的控制器,并且是从主堆栈中的任何其他控制器推送的,那么您只需要调用它:

self.navigationController?.popToRootViewController(animated: true)

您将看到main.stack的根控制器

从任何其他控制器到任何其他控制器的Main.storyboard中的根目录的简短规则,无论之前呈现或推送了多少个控制器:

  • 如果您呈现控制器(不在主堆栈中)且它位于其他导航堆栈中,请使用我所描述的navigateToTheRoot()方法

  • 如果您的控制器被推(推送segues或navigationController?.pushViewController以便以编程方式使用)使用navigationController?.popToRootViewController

  • 如果您的控制器被呈现(是模态)并且它只是没有导航的单个控制器,只需调用self.dismiss(animated:true,completion:nil)

希望它会对你有所帮助。你可以问我是否需要

P.S。在您的注册控制器中(当用户点击“Зарегистрироваться”时显示)有一个小错误“Зарегестрироваться”。 Удачи! ;)