Swift以编程方式导航到另一个视图控制器/场景


81

我正在使用以下代码以编程方式导航到另一个ViewController。它可以正常工作,但是在某种程度上隐藏了navigation bar我该如何解决?(如果需要ViewControllernavigation controller话,可以通过将嵌入来创建导航栏。)

let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)

let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("nextView") as NextViewController
self.presentViewController(nextViewController, animated:true, completion:nil)

Answers:


200

迅捷5

默认的模式演示样式是卡片。这在顶部显示了以前的视图控制器,并允许用户滑动显示的视图控制器。

为了保留旧样式,您需要修改视图控制器,如下所示:

newViewController.modalPresentationStyle = .fullScreen

对于以编程方式创建和情节提要创建的控制器来说都是相同的。

迅捷3

使用以编程方式创建的控制器

如果要导航到以编程方式创建的Controller,请执行以下操作:

let newViewController = NewViewController()
self.navigationController?.pushViewController(newViewController, animated: true)

使用Storyboard创建的控制器

如果要使用标识符“ newViewController”导航到StoryBoard上的Controller,请执行以下操作:

let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
        self.present(newViewController, animated: true, completion: nil)

2
故事板选项中不需要“ as!NewViewController”
Lavi Avigdor

2
是的,我知道这是可选的,但是如果显示,则可以清楚地看到哪个viewcontroller是另一个开发人员的目标
jaiswal Rajan

4
从主线程调用storyBoard.instantiateViewControllerself.present,否则您将在出现viewController组件时出现延迟
Alex

2
@Alex看,是由开发人员从主线程调用它的,我刚刚写了上面问的问题的答案。您从主线程调用的注释在这里不合适。
Jaiswal Rajan '18

嗨,偷看:通常来说,我可以建议一种友善的语气吗?(关于SO,这是一个相当大的问题),相反,它是一个主题:尽管OP并没有直接询问,但我认为这个好答案仍然是记住(对于任何阅读者而言)必须在主线程上进行操作的地方
superjos

32

SWIFT 4.x

用双引号引起来的字符串总是使我感到困惑,因此我认为这个问题的答案需要一些图形化的呈现方式才能解决。

对于银行应用程序,我有一个LoginViewController和BalanceViewController。每个都有各自的屏幕。

该应用程序启动并显示“登录”屏幕。登录成功后,应用程序将打开“余额”屏幕。

外观如下:

在此处输入图片说明

在此处输入图片说明

登录成功的处理方式如下:

let storyBoard: UIStoryboard = UIStoryboard(name: "Balance", bundle: nil)
let balanceViewController = storyBoard.instantiateViewController(withIdentifier: "balance") as! BalanceViewController
self.present(balanceViewController, animated: true, completion: nil)

如您所见,代码第二行中用小写字母表示的情节提要ID是“平衡”,这是在情节提要设置中定义的ID,如随附的屏幕截图所示。

带有大写字母B的术语“ Balance”是情节提要文件的名称,它在代码的第一行中使用。

我们知道在代码中使用硬编码的Strings是非常糟糕的做法,但是在iOS开发中以某种方式它已经成为一种常见的做法,而Xcode甚至没有警告它们。


精彩表演
Elias Fazel

1
老兄,你太棒了!
OhhhThatVarun

15

您应该使用当前不存在的导航控制器来推送新的viewcontroller。

self.navigationController.pushViewController(nextViewController, animated: true)

我们为什么要推动有什么好处?
DragonFire '19

1
@DragonFire,因为op希望它能在不覆盖导航栏的情况下工作。如果要在诸如whatsapp的联系人屏幕和聊天屏幕之间使用主从页面设计,则必须push将Viewcontroller和您的navigationcontroller一起使用。(从左到右制作动画)(如果您只想在当前屏幕上显示,呈现和弹出(从下到上制作动画),请使用present
Okan Kocyigit,

12

根据@jaiswal Rajan的回答。您可以像这样执行pushViewController:

let storyBoard: UIStoryboard = UIStoryboard(name: "NewBotStoryboard", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "NewViewController") as! NewViewController
self.navigationController?.pushViewController(newViewController, animated: true)

1
嗨,您只是想知道:为什么要重复已经发布的答案?也许发表评论或投票也可以。还是背后还有其他理由?
superjos

他正在演示如何使用NavigationController进行导航。谢谢。
Hiran DA Walawage,

4

因此,如果您提供视图控制器,它将不会显示在导航控制器中。它将仅显示完整的屏幕。对于这种情况,您必须创建另一个导航控制器,并nextViewController为此添加您的根用户,并显示此新的navigationController。

另一种方法是只推视图控制器。

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

有关更多信息,请查看Apple文档:-https : //developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/doc/uid/TP40006926-CH3-SW96


presentViewController已重命名为 present(loginController, animated:true, completion:nil)
kite_n_code

2
OperationQueue.main.addOperation {
   let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
   let newViewController = storyBoard.instantiateViewController(withIdentifier: "Storyboard ID") as! NewViewController
   self.present(newViewController, animated: true, completion: nil)
}

当我将代码放在中时,它对我有用OperationQueue.main.addOperation,它将在我的主线程中执行。


1

上面的代码很好用,但是如果要从一个NSObject类导航,则不能使用self.present

let storyBoard = UIStoryboard(name:"Main", bundle: nil)
if let conVC = storyBoard.instantiateViewController(withIdentifier: "SoundViewController") as? SoundViewController,
    let navController = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {
    
    navController.pushViewController(conVC, animated: true)
}

0

所有其他答案听起来都不错,我想介绍一下我的情况,我必须制作一个动画的LaunchScreen,然后在动画3到4秒后,下一个任务是移到主屏幕。我尝试了segues,但是这为目标视图创建了问题。因此,最后我访问了AppDelegates的Window属性,并为其分配了一个新的NavigationController屏幕,

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let homeVC = storyboard.instantiateViewController(withIdentifier: "HomePageViewController") as! HomePageViewController

//Below's navigationController is useful if u want NavigationController in the destination View
let navigationController = UINavigationController(rootViewController: homeVC)
appDelegate.window!.rootViewController = navigationController

如果万一,您不希望在目标视图中使用navigationController,则只需将其分配为,

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let homeVC = storyboard.instantiateViewController(withIdentifier: "HomePageViewController") as! HomePageViewController
appDelegate.window!.rootViewController = homeVC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.