如何在 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?