【问题标题】:Accessing UINavigationController from rootVC Subview (subview loaded from Nib)从 rootVC 子视图访问 UINavigationController(从 Nib 加载的子视图)
【发布时间】:2016-05-10 19:46:11
【问题描述】:

主 ViewController 嵌入在 UINavigationController 子类中,VC 有一个从 nib 加载的子视图。子视图称为 MenuView,并包含将链接到其他 VC 的 UIButton。

为了让我的主 ViewController 不那么不守规矩,我将所有这些按钮放入一个子视图中,该子视图从一个 nib 加载,该笔尖为菜单打开和关闭设置动画。

但是,我想展示其他视图控制器,有时是“模态”,有时是“显示”。我所做的似乎有效,但我只想知道这是否可行,或者我是否造成了一些我不知道的不良影响(例如会导致内存泄漏的强引用循环或其他东西)。或者有更好的方法吗?

一些代码: 在 MenuView.swift 中

class MenuView: UIView {
    var navigationController = CustomNavigationController()

    func combinedInit(){
        NSBundle.mainBundle().loadNibNamed("MenuViewXib", owner: self, options: nil)
        addSubview(mainView)
        mainView.frame = self.bounds
    }

    @IBAction func optionsAction(sender: AnyObject) {
        self.navigationController.performSegueWithIdentifier("presentOptions", sender: self)
    }

在 ViewController.swift 中

        menuView.navigationController = self.navigationController as! CustomNavigationController

【问题讨论】:

    标签: swift uinavigationcontroller subview nib


    【解决方案1】:

    简答:不,不能从层次结构中的某个视图中访问视图控制器,因为这会破坏所有编写的MVC 规则。


    UIView 对象用于在屏幕上显示 UI 组件,并负责正确绘制和布置其子视图。这就是全部。不多也不少。

    您应该始终在相关视图实际所属的控制器中处理视图和控制器之间的此类交互。如果您需要从视图向其视图控制器发送消息,您可以使用delegate approachNSNotificationCenter 类。

    如果我站在你的立场上,当视图需要来自视图控制器的一些信息时,我会使用委托。它比使用通知中心更容易理解,因为它更容易跟踪之间发生的事情。如果视图控制器需要来自视图的一些信息(换句话说,反过来),我会选择通知中心。

    protocol MenuViewDelegate: class {
      func menuViewDidClick(menuView: MenuView)
    }
    
    class MenuView: UIView {
      var weak delegate: MenuViewDelegate?
    
      @IBAction func optionsAction(sender: AnyObject) {
        delegate?.menuViewDidClick(self)
      }
    }
    

    让我们看看视图控制器端发生了什么:

    class MenuViewController: UIViewController, MenuViewDelegate {
    
      override func viewDidLoad() {
        ...
        self.menuView.delegate = self
      }
    
      func menuViewDidClick(menuView: MenuView) {
        navigationController?.performSegueWithIdentifier("presentOptions", sender: self)
      }
    }
    

    有关 iOS 中的通信模式的更多信息,您可能想看看这个很棒的 article 以了解它们的工作原理。

    【讨论】:

    • 感谢您的回答。我正在考虑使用委托,因为它们很容易理解。在委托的情况下,我只是编写了一个带有像 presentViewController(segueKey: String) 这样的函数的协议,然后将该函数放在我的主视图控制器中,并将 menuView.delegate 分配给 self。对吗?
    • 是的,完全一样。我已经更新了我的答案,这样你就可以看到我会如何使用委托。
    • 太棒了,谢谢。快速提问:为什么需要在 menuViewDidClick 方法中将 sender 作为参数传递给 ViewController?
    • 我没有在委托回调中传递sender。刚刚通过了视图self,它让代表知道被点击的是这个视图。当然,您不必传递任何内容,但最好让代理知道此时它正在处理什么视图。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多