以编程方式创建带有后退按钮的导航控制器

Programmatically create navigation controller with back button

我无法在我的 AppDelegate 的 swift 中找到一些东西。数周以来,我一直在研究这个小问题(在后台,而不是持续进行),并进行了大量的谷歌搜索。我一定是遗漏了什么。

当远程通知进入我的 iOS 应用程序时,我想以模式方式呈现适合该消息的视图,以及带有后退按钮的 UINavigationController。这个想法是,当用户处理完通知后,他们可以按 "Back" 并返回到原来的位置。我无法让 "Back" 按钮以编程方式显示在我的导航控制器中。

并非我现有的所有视图都嵌入到导航控制器中。因此,我没有在堆栈中找到现有的 UINavigationController,而是一直在创建一个新的 UINavigationController 并尝试设置它并像这样呈现它:

    let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    var mvc = mainStoryboard.instantiateViewControllerWithIdentifier("MyViewIdentifier") as! MySpecialViewController

    /* here is where I setup the necessary variables in the mvc view controller, using data from the remote message.  You don't need to see all that */

    /* this seems to work, I do get what looks to be a navigation controller */
    let newNavController = UINavigationController(rootViewController: mvc)

    /* this part doesn't work, I don't get a "Back" button */
    let btn = UIBarButtonItem(title: "back", style: UIBarButtonItemStyle.Done, target: mvc, action: "backPressed")
    newNavController.navigationItem.leftBarButtonItem = btn

    /* this block seems to work.  The idea is to work through the hierarchy of any modal presentations
    until we get to the screen that is actually showing right now.  I'm not    
    sure this will work in all situations, but it seems to work in my app's hierarchy. */
    var currentViewController = self.window!.rootViewController
    while currentViewController?.presentedViewController != nil {
        currentViewController = currentViewController?.presentedViewController
    }

    /* this I suppose shows my new view controller modally, except without
    the "back" button it's hard to be sure the navigation controller is even there. */
    currentViewController?.presentViewController(newNavController, animated: true, completion: nil)

我在相关的视图控制器中确实有一个名为 "backPressed" 的方法。

关于导航栏按钮为何未显示的任何线索?

编辑:我知道 backBarButtonItem 只有在我们不在堆栈顶部时才会出现。但是,即使我们在堆栈的顶部,leftBarButtonItem 也应该出现吗?

这是一个简单的例子,可以从第一个视图以编程方式设置导航栏:

if let resultController = storyboard!.instantiateViewControllerWithIdentifier("SecondView") as? SecondView {
    let navController = UINavigationController(rootViewController: resultController) // Creating a navigation controller with resultController at the root of the navigation stack.
    self.presentViewController(navController, animated:true, completion: nil)
}

如果您想将后退按钮添加到该导航中,请将此代码用于 SecondView.swift class:

override func viewDidLoad() {
super.viewDidLoad()

   let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "goBack")
   navigationItem.leftBarButtonItem = backButton

}

func goBack(){
    dismissViewControllerAnimated(true, completion: nil)
}

如果您想从 firstView 完成所有这些,那么您的代码如下:

@IBAction func btnPressed(sender: AnyObject) {


if let resultController = storyboard!.instantiateViewControllerWithIdentifier("SecondView") as? SecondView {
    resultController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "goBack")
    let navController = UINavigationController(rootViewController: resultController) // Creating a navigation controller with VC1 at the root of the navigation stack.
    self.presentViewController(navController, animated:true, completion: nil)
    }
}

func goBack(){
    dismissViewControllerAnimated(true, completion: nil)
}

希望对您有所帮助。

我认为你的视图控制器被不止一个 segue 使用?

在故事板中,您可以将视图控制器嵌入到导航控制器中。

对于模态呈现,您选择导航控制器而不是视图控制器。这将为模式演示提供一个栏。

“完成”按钮更可能用于关闭模式演示。 (用户可能会对后退按钮的非典型使用感到困惑,因为您提供的导航控制器不会从其堆栈中弹出视图控制器。)