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

Posted

技术标签:

【中文标题】以编程方式创建带有后退按钮的导航控制器【英文标题】:Programmatically create navigation controller with back button 【发布时间】:2015-06-01 07:21:22 【问题描述】:

我无法在我的 AppDelegate 中快速解决问题。数周来,我一直在研究这个小问题(在后台,而不是连续),并进行了大量的谷歌搜索。我一定是错过了什么。

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

并非所有我现有的视图都嵌入在导航控制器中。因此,我没有在堆栈中找到现有的 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 也应该出现?

【问题讨论】:

【参考方案1】:

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

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 类:

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)

希望这会对你有所帮助。

【讨论】:

好的,谢谢!整个问题是我试图将 leftBarButtonItem 添加到 UINavigationController。事实上,当它需要添加到导航控制器内的实际视图时:mvc.navigationItem.leftBarButtonItem = ... 非常感谢!你拯救了我的一天:)【参考方案2】:

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

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

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

完成按钮更有可能用于关闭模式演示。 (用户可能会对后退按钮的非典型用法感到困惑,因为您呈现的导航控制器并未将视图控制器从其堆栈中弹出。)

【讨论】:

我不是已经开始使用导航控制器了吗?我在做:presentViewController(newNavController, animated: true, completion: nil) 你有let newNavController = UINavigationController(rootViewController: mvc) ... 好像你应该在代码中创建它并设置它的后退按钮。您不必实例化任何东西,因为 segue 会为您完成。另外,您可以直接从 Storyboard 中的按钮开始,而不必以编程方式呈现视图控制器。您需要传递的任何值都可以在prepareForSegue:sender: Storyboard segues = less code 中完成。 但是感谢您使用“完成”而不是“返回”的建议。 这是对 APNS 消息的响应,因此我将在用户碰巧在的任何屏幕上放置一个模态演示。要在 Storyboard 中做到这一点,我是否必须从整个应用程序中的每个屏幕绘制 segues 到这个视图?因为我需要继续查看这个视图,但不知道用户已经在哪个视图上。可以是任何东西。所以这就是为什么我以编程方式而不是在情节提要中做这个。 (我所有的其他人都在故事板中。) 是的,这很有道理!我只是想建议直接从情节提要中实例化导航控制器,以避免在代码中创建一个。您现在已经从另一个答案中获得了代码,一切都很好! :)

以上是关于以编程方式创建带有后退按钮的导航控制器的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式导航控制器后退按钮标题(无情节提要)[重复]

以编程方式调用 iOS 上的导航控制器后退按钮

显示带有返回按钮的导航控制器

导航视图控制器不显示后退按钮

在导航控制器中设置后退按钮

如何使用Android中的导航控制器制作自定义后退按钮以返回某个目的地?