视图模型和视图如何通信?

时间:2019-11-08 12:12:36

标签: ios swift solid-principles

最近我正在阅读有关依赖反转的原理,该原理指出高级模块不应依赖于低级模块,它们都应依赖于抽象。

protocol ViewControllerProtocol {
    func saveButtonTapped()
}

struct ViewModel : ViewControllerProtocol{
    func saveButtonTapped() {
        //save data...
        print("forward save request")
    }

     func statusArrived(){
       // inform viewcontroller about updating UI
    }
}


class ViewController: UIViewController {

    private var  vm : ViewControllerProtocol?

    required init(viewmodel : ViewModel){
        self.vm = viewmodel
        super.init(nibName: nil, bundle:nil)
    }

    @IBAction func btnSaveTapped(_ sender: Any) {
        vm?.saveButtonTapped()
    }


}

遵循依赖性反转原则,我能够在viewcontroller-> Viewmodel之间进行通信。

我的问题是,如何反向交流?即。形成视图模型以查看控制器? 我在想,通过创建另一个协议,viewcontroller实现该协议。...

如何反向交流?即。表单视图模型以查看控制器?

3 个答案:

答案 0 :(得分:0)

您可以使用闭包来返回调用。

class ViewController: UIViewController {

    private var  vm : ViewControllerProtocol?

    required init(viewmodel : ViewModel){
        self.vm = viewmodel
        super.init(nibName: nil, bundle:nil)

        self.vm.savedSuccessfully = {
            // do stuff
        }
    }

    @IBAction func btnSaveTapped(_ sender: Any) {
        vm?.saveButtonTapped()
    }


}

struct ViewModel : ViewControllerProtocol{

    var savedSuccesfully: (() -> ())?
    func saveButtonTapped() {
        //save data...
        print("forward save request")
    }

     func statusArrived(){
       // inform viewcontroller about updating UI
       savedSuccesfully?()
    }
}

答案 1 :(得分:0)

只要ViewModel不拥有View,就可以使用委托模式从ViewModel到View进行通信,即没有对View的强引用。

作为替代解决方案,您还可以查看Observer Pattern,将消息从ViewModel传递到View。实际上,这就是RxSwift之类的库为您提供的。

如果您查看了显示依赖关系反转的类图,那么在MVVM的情况下,从ViewModel到View的关联始终显示在虚线中,并带有指向View的箭头。这只是意味着ViewModel知道View,但是对它没有任何强引用。

答案 2 :(得分:0)

将结束添加为完成处理程序

protocol ViewControllerProtocol {
     func saveButtonTapped(completionHandler: ()->())
 }

实施

struct ViewModel : ViewControllerProtocol{
    func saveButtonTapped(completionHandler: () -> ()) {
        print("forward save request")

        completionHandler()
    }
}

这是您现在可以使用的方式:-

@IBAction func btnSaveTapped(_ sender: Any) {
     vm?.saveButtonTapped { [weak self] in

         /// From ViewModel -> ViewController
     }
 }

如果您要在该闭包内使用viewController,请不要忘记添加捕获列表以避免保留周期。