容器视图控制器中的委托

时间:2018-05-18 22:33:04

标签: ios swift uiviewcontroller delegates delegation

我有一个托管3个容器viewcontrollers的父视图控制器。

在某些时候,我需要将数据从一个容器viewcontroller传递到另一个容器viewcontroller,并认为我可以通过委托模式完成此操作。但是,我似乎无法弄清楚为什么代理没有被触发,接收容器视图控制器也没有收到任何数据。

似乎无法发现我设置方式可能出现的问题。如果有推荐的方法在容器之间传递数据,我也是耳朵!

以下是有关设置的代码摘要:

class ParentViewController: UIViewController { 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let firstContainerVC = segue.destination as? FirstContainerVC {
            //....
        }

        if let secondContainerVC = segue.destination as? SecondContainerVC {
           //....
        }        
    }
        protocol Delegate {
           func passX(a: String?)
           func passY(b: String?)
        }
}    

class FirstContainerVC: UIViewController {

    var delegate: Delegate?

    if isTrue {
        delegate.passX(a: "TestOne")
    } else {
        delegate.passY(b: "TestTwo")
    }
}

class SecondContainerVC: UIViewController, Delegate {

    override func viewDidLoad() {
        let firstVC = self.storyboard?.instantiateViewController(withIdentifier: "firstContainer") as! FirstContainerVC
    firstVC.delegate = self
    }

    func passX(a: String?) {
        //if let a = a....
    }

    func passY(b: String?) {
        //if let b = b....
    }
}

2 个答案:

答案 0 :(得分:0)

我同意@slickdaddy您的第二个容器视图控制器没有业务实例化您的第一个容器视图控制器。我怀疑你已经有了第一个容器VC,现在你已经有了2个。

要回答有关传递数据的最佳方法的问题,容器视图控制器应该对父视图控制器一无所知。通过委托或父级注册的回调,数据应该转到父级,然后父级应该将其路由到其他感兴趣的包含视图控制器。

让您的层次结构“向下”流畅。换句话说,包含或拥有的风险投资公司不应该知道有关其所有者或父母的任何信息。它将有助于重用,组织等。

还要考虑另一种方法:将相同的模型对象传递到每个包含的视图控制器中。

最后,我首选的方法是让每个视图控制器(或实际上它的视图模型,如果做MVVM)到达这样的模型对象所在的DependencyManager单例。如果完成,单元测试仍然可以通过将模拟模型注入DependencyManager来完全控制。

答案 1 :(得分:0)

不幸的是,我不知道Xcode中的拖放是如何工作的,我在代码中做了一切。但是,当您的父视图控制器实例化另一个视图控制器时,只需将父视图设置为容器的委托。

创建协议:

protocol SomeProtocol: AnyObject {
    func passX(a: String?)
    func passY(b: String?)
}

容器将具有协议类型的委托:

class FirstContainerVC: UIViewController {
    weak var delegate: SomeProtocol?
}

class SecondContainerVC: UIViewController {
    weak var delegate: SomeProtocol?
}

父级必须符合协议,以便它可以成为委托。然后,当您实例化容器(在此方案中只能执行一次)时,将self设置为其代理:

class ParentViewController: UIViewController, SomeProtocol {

    // make the containers instance properties so that you
    // can access them from the protocol methods
    weak var firstContainerVC = FirstContainerVC()
    weak var secondContainerVC = SecondContainerVC()

    // set the delegates at some point
    func setDelegates() {
        firstContainerVC?.delegate = self
        secondContainerVC?.delegate = self
    }

    func passX(a: String?) {
        guard let a = a else {
            return
        }
        secondContainerVC?.getFromFirst(a: a)
    }

    func passY(b: String?) {
        //
    }

}

然后,当您想要从第一个容器转到第二个容器时,请通过委托从第一个容器到父容器,从父容器到第二个容器。

class FirstContainerVC: UIViewController {

    weak var delegate: SomeProtocol?

    func sendToSecond() {
        delegate?.passX(a: "slick")
    }

}

class SecondContainerVC: UIViewController {

    weak var delegate: SomeProtocol?

    func getFromFirst(a: String) {
        print(a)
    }

}

这是一个有点粗略的例子。您应该以最舒适的方式编写实现代码(即优雅地展开,实例化的方式/位置等)。此外,如果所有视图控制器都是永久视图控制器(意味着它们永远不会被释放),则无需进行weak var。无论如何,这些概念都是一样的。父对象是容器的委托,容器通过父对象相互通信。

有些人可能会建议使用通知观察员或单身人士来让容器相互沟通,但我发现当你的父母就在那里时会有些过分。