ios - 在 MVVM 中设置委托(delegate)的正确方法

标签 ios swift mvvm delegates

我想知道在 Swift 的 MVVM 模式中的 ViewModel 中设置委托(delegate)的正确方法是什么。

我正在从另一个类中实例化 ViewController:

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

我的 View 模型:

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)
        }
    }
}

和 View Controller :

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")
    }
}

所以主要问题是,如果我想在另一个类中注入(inject) viewModel,我将在尚未设置委托(delegate)时实例化 viewModel。在 DashboardViewModelType 协议(protocol)中声明 loadItems 然后从 ViewController 中的 init 或 viewDidLoad 调用此函数会更好吗?

最佳答案

是的,您可以在 DashboardViewModelinit 中注入(inject) DatabaseDaysFetcher,然后如您所说,移动 loadItemsDashboardViewModelType 协议(protocol)。

然后当您调用 loadItems 时,它应该回调给调用者。 然后在 loadItems 回调中使用 [weak self]。

这将否定对 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)
        }
    }
}

关于ios - 在 MVVM 中设置委托(delegate)的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50281175/

相关文章:

ios - 你如何设置 map 的标题?

swift - 使用 Parse.com Swift 调用 Twitter API

c# - 让 WPF 控件触发和设置另一个控件的 itemssource

ios - 仅当来自服务器的数据快速加载到第一个 View Controller 的核心数据中时,如何运行第二个 View Controller

wpf - 从 View 模型类调用 RichTextBox.ScrollToEnd()

c# - WPF MVVM 代码背后的最佳实践

ios - navigationItem 上的 UIImageView 尺寸错误

iphone - Xcode 5、iOS7 和 64 位与 32 位

ios - 在 iOS 的自定义抽屉导航中状态栏颜色更改为白色?

ios - Apple DeviceCheck API 每分钟最大请求数