Как viewmodel и view общаются? - PullRequest
       32

Как viewmodel и view общаются?

0 голосов
/ 08 ноября 2019

недавно я читал о принципе инверсии зависимостей, который гласит, что модуль высокого уровня не должен зависеть от модуля низкого уровня, они оба должны зависеть от абстракции.

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 голосов
/ 08 ноября 2019

Использование шаблона делегата для связи из ViewModel в View - это нормально, если ViewModel не является владельцем View, то есть нет строгой ссылки на View.

В качестве альтернативного решения вы также можете посмотреть на шаблон наблюдателя для передачи сообщений из ViewModel в View. Фактически, это то, что предоставляют библиотеки типа RxSwift.

Если вы когда-нибудь посмотрите на диаграмму классов, показывающую инверсию зависимостей, в случае MVVM связь между ViewModel и View всегда отображается в пунктирной линии. со стрелкой, указывающей на вид. Это просто означает, что ViewModel знает о View, но не имеет к нему четкой ссылки.

0 голосов
/ 08 ноября 2019

Добавить замыкание в качестве обработчика завершения

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 внутри этого замыкания.

0 голосов
/ 08 ноября 2019

Вы используете замыкания для возврата вызова.

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?()
    }
}
...