【问题标题】:How to have a top left navigation cancel button, for a UIViewController created from XIB?对于从 XIB 创建的 UIViewController,如何设置左上角导航取消按钮?
【发布时间】:2021-02-16 17:11:59
【问题描述】:

在 Stroyboard 中,将 UIViewController 嵌入到导航控制器中非常简单,然后可以添加 UIBarButtonItem 取消按钮,用于展开目的。

但是,我想知道,如果我们的 UIViewController 是从 XIB 创建的,我们该怎么做?

我有以下自定义视图,它呈现模态 UIViewController

class CustomColorView: UIView {
    @objc func textViewWasTapped() {
        let hexColorStringInputVC = HexColorStringInputVC.instanceFromNib()
        
        let navController = UINavigationController(rootViewController: hexColorStringInputVC)

        // Cancel button not visible. Not sure why?!
        navController.navigationItem.setLeftBarButton(UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: nil), animated: true)
        
        UIViewController.topViewController()?.present(navController, animated: true, completion: nil)
    }
    ...
}

extension UIViewController {
    static func instanceFromNib() -> Self {
        func instantiateFromNib<T: UIViewController>() -> T {
            return T.init(nibName: String(describing: T.self), bundle: nil)
        }

        return instantiateFromNib()
    }
    
    static func topViewController() -> UIViewController? {
        let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
        
        guard var top = keyWindow?.rootViewController else {
            return nil
        }
        
        while let next = top.presentedViewController {
            top = next
        }
        
        return top
    }
}

textViewWasTapped 执行时,如下所示。

  1. 是否需要在 UINavigationController 中嵌入 UIViewController
  2. 为什么通过navController.navigationItem.setLeftBarButton 看不到左上角的取消按钮?
  3. 如何在导航取消按钮上添加展开操作?
  4. 在 XIB 中是否有更简单的操作,就像 Storyboard 一样简单?

【问题讨论】:

    标签: ios swift


    【解决方案1】:
    1. 是否需要在 UINavigationController 中嵌入 UIViewController?

    这取决于你想做什么。如果您不想使用手动添加的UINavigationBar 创建自定义视图,那么这是在视图中获取UINavigationBar 的最简单方法。

    1. 为什么通过navController.navigationItem.setLeftBarButton 看不到左上角的取消按钮?

    Apple Documentation中所述:

    导航控制器使用与导航堆栈上的视图控制器关联的导航项对象(UINavigationItem 类的实例)动态构建导航栏的内容。要自定义导航栏的整体外观,请使用 UIAppearance API。因此,要更改导航栏的内容,您必须配置自定义视图控制器的导航项。有关导航项的更多信息,请参阅 UINavigationItem。

    这意味着您必须将UIBarButtonItem 添加到您的UIViewController 实例而不是UINavigationController 实例。在您的示例中,这将是:

    hexColorStringInputVC.navigationItem.setLeftBarButton(UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: nil), animated: true)
    
    1. 如何在导航取消按钮上添加展开操作?

    如果您的意思是“展开操作”导航回以模态方式呈现当前子视图控制器的父视图控制器,那么您必须在子视图控制器上使用 dismiss(animated:completion:) 方法。在您的示例中,这将是:

    ...
    hexColorStringInputVC.navigationItem.setLeftBarButton(UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelButtonPressed)), animated: true)
    ...
    @objc func cancelButtonPressed(_ sender: UIBarItem) {
        navController.dismiss(animated: true)
    }
    

    当然navController 变量必须在范围内。

    如果您必须来回传递数据,那么有很多关于这个主题的教程。我建议从委托模式开始。

    1. 在 XIB 中是否有更简单的操作,就像 Storyboard 一样简单?

    如果您的意思是“更容易”在带有代理对象的界面构建器中执行此操作,那么没有。

    当我在 xib 文件中为视图控制器创建主视图时,我在他的视图控制器中声明控制操作方法。

    【讨论】:

      猜你喜欢
      • 2019-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-07
      相关资源
      最近更新 更多