使用NavigationViewController在Swift中展示ViewController

81

我有一个系统 "NavigationViewController -> MyViewController",我想以编程方式在第三个视图控制器中呈现MyViewController。问题是,在呈现后,MyViewController 中没有导航栏。你能帮我吗?

var VC1 = self.storyboard.instantiateViewControllerWithIdentifier("MyViewController") as ViewController
self.presentViewController(VC1, animated:true, completion: nil)
5个回答

233

调用 presentViewController 方法,以模态(modal)的方式呈现视图控制器,它将呈现在已有的导航堆栈之外;也就是说,它不属于您的 UINavigationController 或任何其他导航控制器。如果您希望您的新视图控制器具有导航栏,您有两个主要选项:

选项 1. 将新视图控制器推入您现有的导航堆栈中,而不是以模态形式呈现:

let VC1 = self.storyboard!.instantiateViewControllerWithIdentifier("MyViewController") as! ViewController
self.navigationController!.pushViewController(VC1, animated: true)

选项2:将您的新视图控制器嵌入到新的导航控制器中,并以模态方式呈现新的导航控制器:

let VC1 = self.storyboard!.instantiateViewControllerWithIdentifier("MyViewController") as! ViewController
let navController = UINavigationController(rootViewController: VC1) // Creating a navigation controller with VC1 at the root of the navigation stack.
self.present(navController, animated:true, completion: nil)

请记住,这个选项不会自动包含一个“返回”按钮。您需要自己构建关闭机制。

哪种选项最适合您是一个人机界面设计问题,但通常很清楚什么是最有意义的。


1
如何使新的视图控制器从右到左而不是从底部向上呈现?谢谢。 - vincwng
6
好的。但是我该如何关闭模态框? - Peter Kreinz
我的视图控制器(ViewController)已经通过StoryBoard与NavigationController链接。然后选项1不起作用,它显示没有导航栏的导航控制器! - kiran
1
如果你看到双重NavigationBar,请写下这行代码。 navController.isNavigationBarHidden = true - Neeraj Joshi
@PeterKreinz 可能有点晚了,但可能会对某些人有所帮助。我使用 XCode 13 和 iOS 11.4 的 iPhone 7 模拟器,发现上述解决方案可行,但未以模态方式显示 VC1。然而,当我在实际的 iPhone 上运行相同的代码时,该视图以模态方式显示。 - Gavin
第二个选项不适用于iPhone 12或iPhone XR。它适用于iPhone 7和iPod第七代。是否有一种通用的解决方案? - es1

17

SWIFT 3

let VC1 = self.storyboard!.instantiateViewController(withIdentifier: "MyViewController") as! MyViewController
let navController = UINavigationController(rootViewController: VC1)
self.present(navController, animated:true, completion: nil)

15

我的导航栏没有显示,所以我在 Swift 2 iOS 9 中使用了以下方法

let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("Dashboard") as! Dashboard

// Creating a navigation controller with viewController at the root of the navigation stack.
let navController = UINavigationController(rootViewController: viewController)
self.presentViewController(navController, animated:true, completion: nil)

2
最初的回答很好。这不是一个答案,只是对问题的说明。
我展示了一个像这样的视图控制器:
在vc1内部:
func showVC2() {
    if let navController = self.navigationController{
        navController.present(vc2, animated: true)
    }
}

VC2内部:

最初的回答
func returnFromVC2() {
    if let navController = self.navigationController {
        navController.popViewController(animated: true)
    }else{
        print("navigationController is nil") <-- I was reaching here!
    }
}

正如'stefandouganhyde'所说:“它不受您的UINavigationController或任何其他控制器的限制”

新解决方案:

func returnFromVC2() {
    dismiss(animated: true, completion: nil)
}

1

我使用了一个扩展到UIViewController和一个结构体,以确保我的当前视图是从收藏夹中显示的

1. 用于全局布尔值的结构体

struct PresentedFromFavourites {
static var comingFromFav = false}

2.UIVeiwController扩展:以第二个选项“stefandouganhyde - Option 2”的方式模态呈现,并解决返回问题

extension UIViewController {
func returnToFavourites()
{
    // you return to the storyboard wanted by changing the name
    let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
    let mainNavigationController = storyBoard.instantiateViewController(withIdentifier: "HomeNav") as! UINavigationController
    // Set animated to false
    let favViewController = storyBoard.instantiateViewController(withIdentifier: "Favourites")
    self.present(mainNavigationController, animated: false, completion: {
        mainNavigationController.pushViewController(favViewController, animated: false)
    })

}
// call this function in viewDidLoad()
// 
func addBackToFavouritesButton()
{
    if PresentedFromFavourites.comingFromFav
    {
        //Create a button
        // I found this good for most size classes
        let buttonHeight = (self.navigationController?.navigationBar.frame.size.height)! - 15
        let rect = CGRect(x: 2, y: 8, width: buttonHeight, height: buttonHeight)
        let aButton = UIButton(frame: rect)
        // Down a back arrow image from icon8 for free and add it to your image assets  
        aButton.setImage(#imageLiteral(resourceName: "backArrow"), for: .normal)
        aButton.backgroundColor = UIColor.clear
        aButton.addTarget(self, action:#selector(self.returnToFavourites), for: .touchUpInside)
        self.navigationController?.navigationBar.addSubview(aButton)
        PresentedFromFavourites.comingFromFav = false
    }

}}

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