如何在 Swift 中加载初始视图控制器?

Posted

技术标签:

【中文标题】如何在 Swift 中加载初始视图控制器?【英文标题】:How to load initial view controller in Swift? 【发布时间】:2014-10-30 15:11:25 【问题描述】:

我正在为基于 用户名密码 的系统开发应用程序。我的初始视图控制器名为LoginPageViewController。如果用户登录成功,则会加载一个名为MyNavigationController 的导航控制器。除了LoginPageViewController 之外的所有视图控制器都可以通过我在此处找到的侧边菜单访问:Side Menu Library 在MyNavigationController 的帮助下。

我的侧边菜单的视图设置在MyMenuTableViewController 中进行了描述,如果选择了任何表格项,则从MyMenuTableViewController 加载相关的视图控制器。问题是,我还在我的侧边菜单(或菜单表,无论你叫什么)中添加了“注销”项目,如果选择了这个项目,它会向服务器发出 HTTP POST 请求以注销并且应该加载LoginPageViewController,这是我的初始视图控制器(未嵌入MyNavigationControlelr)。

问题是,虽然注销请求处理成功,但我在加载初始视图控制器时遇到了问题(LoginPageViewController)。

当我在选择注销时尝试此操作时:

self.presentViewController(destViewController, animated: true, completion: nil)

LoginPageViewController 正在加载,但我收到如下消息:2014-10-30 16:59:26.038 iOpsGenie[2973:66509] Presenting view controllers on detached view controllers is discouraged <iOpsGenie.MyMenuTableViewController: 0x7f85e8fc3f10>. 如果我点击登录页面上的任何位置,我的视图就会消失,只剩下一个白屏。

然后我尝试实现一个方法

 func resetAppToFirstController() 
     self.window?.rootViewController = LoginPageViewController(nibName: nil, bundle: nil)
     

AppDelegate.swift 中并在选择 Logout 项时调用它:

let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
appDelegate.resetAppToFirstController()

然后我在 LoginPageViewController 的 viewDidLoad 函数的第二行出现错误,例如:

fatal error: unexpectedly found nil while unwrapping an Optional value

我知道这成了一个很长的问题。我可能被视为 Swift 和 ios 编程的新手,我试图陈述问题以防止出现不相关的反应。我真的很想知道我错过了什么。

最好的问候

【问题讨论】:

在 resetApp() 中实例化 LoginPageVC 时,您应该为第一个参数传递 xib 名称而不是 nil。 Swift 不会像 Objective-C 那样找到与 VC 同名的 nib。 【参考方案1】:

我通过将 resetAppToFirstController 方法更改为:

self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier(PageNames.LOGIN_PAGE) as LoginPageViewController

并在单击注销时触发以下代码:

let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
appDelegate.resetAppToFirstController()

但是,我不知道为什么会这样。任何一点解释都会很棒。

【讨论】:

【参考方案2】:

我们可以快速更改根视图控制器,在这种情况下,所有 其他视图控制器将被释放,它们将不再是 在层次结构中。

加载初始视图控制器或更改根视图控制器或在 swift 中进行注销操作

let storyboard = UIStoryboard(name: "StartingPage", bundle: NSBundle.mainBundle())      
let loginView: SignInVC = storyboard.instantiateViewControllerWithIdentifier("SignInVC") as! SignInVC
UIApplication.sharedApplication().keyWindow?.rootViewController = loginView

【讨论】:

谢谢正在寻找这个。 我们可以用动画实现这个功能吗?【参考方案3】:

请允许我提出一个更好的方法来做你想做的事,好吗? 我在发布的另一个问题中遇到了类似的问题;请查看this question 接受的答案。

注意答案上的故事板。它具有视图控制器的层次结构,允许从登录控制器开始,浏览多个控制器并从菜单执行注销。

为了实现这一点,请按照以下步骤操作。

    使您的初始视图控制器成为导航控制器,根视图作为您的登录控制器。

    让您的登录控制器 Push Segue 成为 Menu 控制器。

    从菜单视图的注销按钮到登录视图执行“展开转场”。

展开转场将从导航堆栈中删除所有视图,直到到达您指定的视图。

Unwind segues真的好用,可以解决很多问题!

在您的登录视图控制器上添加以下方法定义:

@IBAction func unwindToLoginScreen(segue:UIStoryboardSegue) 

然后,在情节提要编辑器上,选择您希望能够从中放松的任何视图控制器。在视图控制器的顶部有三个图标。

第一个代表视图控制器;第二个是第一响应者;第三个是出口。

从第一个图标到第三个图标执行“Control+Drag”;将出现一个下拉菜单,引用您对代码所做的所有“unwind segue”声明。我们的 unwindToLoginScreen segue 应该出现在这里。选择它。

在情节提要编辑器左侧栏的文档大纲上,将在视图控制器的层次结构上显示一个 Unwind Segue。选择它并将其标识符更改为“登录”之类的内容。

现在,如果您想返回登录屏幕,可以调用 performSegueWithIdentifier("Login")。

使用 unwind segues 的优点是您可以确定堆栈中的所有视图都正在被释放,您可以在源视图控制器的 prepareForSegue 方法中调用准备代码,在您的目标视图控制器中调用一些代码在完成segue之前;并且不同视图控制器之间的连接在故事板编辑器上是可见的(虽然不像在常规 segues 中那么明显)。

【讨论】:

【参考方案4】:

斯威夫特 4

swift4 中的语法已更改:如果您想转到 StoryBoard "Main" 中的 "FirstViewController" 试试下面的代码

让 storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)

让 firstviewcontroller = storyboard.instantiateViewController(withIdentifier: "FirstViewController") 为!第一视图控制器

UIApplication.shared.keyWindow?.rootViewController = firstviewcontroller

【讨论】:

以上是关于如何在 Swift 中加载初始视图控制器?的主要内容,如果未能解决你的问题,请参考以下文章

Swift 2 - 无法在单独的 ViewController 中加载 UIWebView

如何在 iOS 应用中加载初始 UIViewController?

如何在 UITabBarController 中加载所有视图?

快速在视图控制器中加载集合视图控制器

在初始化程序中加载 webview 内容

Swift:如何使滚动视图执行子视图控制器 viewDidLoad