Правильный способ настройки делегатов в MVVM - PullRequest
0 голосов
/ 10 мая 2018

Я хотел бы знать, как правильно настроить делегатов в ViewModel в шаблоне MVVM в Swift.

Я создаю экземпляр ViewController из другого класса:

let viewModel = DashboardViewModel()
let viewController = DashboardViewController(viewModel: viewModel)

Моя ViewModel:

protocol DashboardViewModelType {
    var items: [Item] { get }
    var reloadDelegate: DashboardDataReloadDelegate? { get set }
}

protocol DashboardDataReloadDelegate: class {
    func reloadData()
}

class DashboardViewModel: DashboardViewModelType {

    var items: [Item] = []

    weak var reloadDelegate: DashboardDataReloadDelegate?

    init() {
        loadItems()
    }

    func loadItems() {
        let databaseFetcher = DatabaseDaysFetcher()
        databaseFetcher.getDays(onData: { (items) in
            self.items = items
            reloadDelegate?.reloadData() //delegate is nil here
        }) { (error) in
            print(error)
        }
    }
}

и ViewController:

class DashboardViewController: UIViewController {

    var viewModel: DashboardViewModelType?

    init(viewModel: DashboardViewModelType) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
        self.viewModel!.reloadDelegate = self // it is executed after 
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad() 
    }

}

extension DashboardViewController: DashboardDataReloadDelegate {
    func reloadData() {
        print("data reloaded")
    }
}

Так что основная проблема заключается в том, что если я хочу внедрить viewModel в другой класс, я создаю экземпляр viewModel, когда делегат нееще не установлено.Было бы лучше объявить loadItems внутри протокола DashboardViewModelType, а затем вызвать эту функцию из init или viewDidLoad внутри ViewController?

1 Ответ

0 голосов
/ 11 мая 2018

Да, вы можете ввести DatabaseDaysFetcher в init для DashboardViewModel, а затем, как вы говорите, переместить loadItems в DashboardViewModelType протокол.

Затем, когда вы звоните loadItems, он должен перезвонить вызывающему. Затем используйте [слабое я] в обратном вызове loadItems.

Это сведет на нет необходимость delegate.

protocol DashboardViewModelType {
    init(databaseFetcher: DatabaseDaysFetcher)
    func loadItems(completion: ([Item]) -> Void, error: (Error) -> Void)
}

final class DashboardViewModel: DashboardViewModelType {

    private var databaseFetcher: DatabaseDaysFetcher

    init(databaseFetcher: DatabaseDaysFetcher) {
        self.databaseFetcher = databaseFetcher
    }

    func loadItems(completion: ([Item]) -> Void, onError: (Error) -> Void) {
        self.databaseFetcher.getDays(onData: { (items) in
            completion(items)
        }) { (error) in
            onError(error)
        }
    }
}
...