如何在Swift中返回到初始视图控制器?

44

我有一个登录视图,在成功登录后,它会跳转到导航控制器的第一个视图,然后用户可以进入设置视图,再进入注销视图。这个注销操作应该将用户带回登录视图(该视图不是导航控制器的一部分)。使用以下代码可以实现:

let loginViewController = self.storyboard!.instantiateViewControllerWithIdentifier("Login") as? LoginViewController
self.navigationController!.pushViewController(loginViewController!, animated: true)

但是登录视图在顶部显示了导航栏,这是不应该的,也许除了self.navigationController!.pushViewController之外还有其他我应该使用的方法吗?

6个回答

89

SWIFT: 你应该使用unwind segue。

  1. 首先,在你的FirstViewController中加入以下代码:

    @IBAction func prepareForUnwind(segue: UIStoryboardSegue) {
    }

    这个函数实际上没有任何代码。


  1. 现在,进入你的Storyboard,通过从黄色按钮拖动到Exit按钮来为LogoutViewController创建一个unwind segue。就像这样:

control-dragging in action

  1. 选择为FirstViewController创建的unwind segue。

  2. 更改segue标识符:

selected segue


changing the identifier of the segue

  1. 进入LogoutViewController代码,直接调用unwind segue:

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

    Swift 4

    self.performSegue(withIdentifier: "unwindToViewController1", sender: self)
    

1
这绝对是最好的答案。 - Canopus
1
第一次就完美无误地工作了,这在开发人员的生活中非常罕见。这个答案在Xcode 8和Swift 3中仍然有效。 - zeeshan
我还陷在这个问题中...当用户登录时,你如何处理这个问题,然后将一个token设置在NSUserdefaults中,使他不必再次登录,而在将来的某个时候,他决定注销时该怎么办?当我尝试这种方法时,“登录”屏幕不再是控制器堆栈中的一部分了,因为我在应用程序启动时跳过了此屏幕,所以我无法返回到登录屏幕。请帮忙! - Matias Contreras
@MatíasContrerasSelman 我也遇到了同样的问题。如果您已经解决了,请帮忙一下。 - Mamta
我不得不重新考虑应用程序第一次启动的方式。我的做法是每次应用程序加载时以编程方式实例化所有起始屏幕,但在用户令牌设置时以编程方式跳转到主屏幕而不需要动画。这样,登录屏幕始终在视图堆栈中,当用户按下“注销”按钮时,我可以解开它。 - Matias Contreras
显示剩余5条评论

29

如果您有一个导航控制器,那么从您的控制器中使用以下代码:

self.navigationController?.popToRootViewControllerAnimated(true)

简单,准确,最佳 - Abdul Waheed
绝对是最好和最简单的答案。 - Berat Cevik
4
在 Swift 4 中,使用 self.navigationController?.popToRootViewController(animated: true)。该语句的作用是返回到导航控制器的根视图控制器,并使用动画效果。 - CanCoder

27

如果您正在使用storyboard,请了解unwind segueing。

您只需要在要导航的控制器中创建unwind选项:

@IBAction func unwindToMe(segue: UIStoryboardSegue){}

然后从Storyboard创建segue。

当您需要返回导航时,只需使用刚刚创建的unwind segue标识符调用performSegue方法。

如果您只想从代码中执行此操作,则可以编写类似以下内容的代码:

let loginViewController = self.storyboard?.instantiateViewControllerWithIdentifier("Login")
UIApplication.sharedApplication().keyWindow?.rootViewController = loginViewController

在这种情况下,您需要将应用程序设置为初始状态。


工作得非常好,非常感谢。 - matt
@matt 第二个变量更好用。它更加自信,而且你不需要从storyboard创建控制器。 - Vasyl Khmil

18

试一下

    self.view.window?.rootViewController?.dismissViewControllerAnimated(true, completion: nil)

这会让您回到应用程序流程的开头。

更新为Swift 4(感谢 @javaBeast)

    self.view.window?.rootViewController?.dismiss(animated: true, completion: nil) 

1
对我来说非常好用,因为我有3个不同的视图,在它们之间我有2个导航控制器。 - Tony Merritt
1
在尝试了其他10种不起作用的解决方案后,这个终于管用了,谢谢!更新至SWIFT 4:self.view.window?.rootViewController?.dismiss(animated: true, completion: nil) - JavaBeast
在 SWIFT 5 中,唯一有效的解决方案是这个。非常感谢! - Flo

1
self.navigationController?.popToRootViewController(animated: true)

前往导航控制器的第一个控制器,然后关闭导航控制器是最好的选择。


0

我建议您使用segue从一个ViewController转到另一个,而不是像那样推送您的ViewController。

首先,您需要从第一个ViewController Ctrl + clic到登录ViewController,然后在属性检查器中为其指定一个标识符。

然后,您只需要这样做:

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

现在,关于导航栏,我建议你从登录视图中移除导航控制器,并将其与你的第一个视图相关联。这样可以从你的登录视图中移除导航栏。

我不相信这与他试图做的事情相符...因为如果你执行performSegueWithIdentifier,你会向窗口栈添加一个新窗口...而不是返回到第一个视图控制器... 最好的答案是Allan提供的答案。 - Agustin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接