使用MVVMC架构在iOS应用程序中调用Web服务的最佳位置是什么?

时间:2017-10-25 12:22:52

标签: ios design-patterns mvvm architecture

目前我正在使用MVVMC架构开发iOS应用程序。我通过阅读article来了解MVVMC。作为典型的MVVM模型,我们知道所有主要的应用程序控制器(如Web服务调用)都应该在ViewModel类中调用。但是在MVVMC架构中,我们可以使用Coordinator或ViewModel来调用Web服务。我无法弄清楚最适合这个的地方。

我目前正在尝试使用UITableViewController实现应用程序的用户列表页面。以下是我的UserCoordinator和UserViewModel类的一些部分。

UserCoordinator

class UsersCoordinator: Coordinator {

var window: UIWindow
weak var delegate: UsersCoordinatorDelegate?

var  selectedCity: City?

init(window: UIWindow) {
    self.window = window
}

func start() {
    let storyboard = UIStoryboard(name: "Users", bundle: nil)
    if let vc = storyboard.instantiateViewController(withIdentifier: "list") as? UsersListController {
        var viewModel = UsersListViewModel()
        viewModel.delegate = self as UsersListViewModelDelegate
        viewModel.veiwController = vc
        vc.viewModel = viewModel
        vc.coordinationDelegate = self as CoordinationDelegate
        let nav = UINavigationController.init(rootViewController: vc)
        window.rootViewController = nav
    }

}

UserViewModel

 protocol UsersListViewModelDelegate: class  {
    func selectUser(viewController: UIViewController, city: City)
}

struct UsersListViewModel {
    var delegate: UsersListViewModelDelegate?
    weak var veiwController: UsersListController!
    var source = [String]()

    init() {
        for user in users {
            source.append(user.name)
        }
    }

    func selectRow(row: NSInteger) {
        delegate?.selectUser(viewController: veiwController, user: users[row])
    }

    fileprivate var users: [User] {
        get {
            //web service call??
        }

我应该在哪里拨打网络服务?正如我从理论上讲,协调器是应用程序路由的专用场所。因此,根据它,在ViewModel中调用Web服务会更好。但我觉得在协调器中调用Web服务会更好,因为它会非常快速地加载数据并填充viewModel。我该怎么办?

3 个答案:

答案 0 :(得分:5)

您需要了解ViewModel和协调器的用途,才能知道其中应包含什么。 ViewModel 的职责是为View准备数据并处理用于准备该数据的业务逻辑。它将数据绑定到UI元素,并在数据更改后立即更改UI。因此,ViewModel应该是其中应包含该服务的对象,并且所有调用均应通过该服务进行。

协调器的职责是通过显示适当的ViewController及其所有依赖项(包括ViewModel)来处理应用程序的导航。因此,它还准备了ViewModel并将其注入服务,而不使用该服务来操纵数据。

所以,我总结一下,协调器应该是准备带有依赖项的ViewModel的人,其中包括在其中注入Web服务,而ViewModel应该是使用该服务并进行所有从持久性获取数据的调用的人。

有关更清晰的主意,您可以在 Github

上的 MVVM-C 上检查我的示例应用程序

答案 1 :(得分:4)

当我通过互联网进行研究时,没有惯例可以调用您的Web服务。它完全取决于您的项目实施。您可以在Coordinator或ViewModel类上调用它们。由于我们使用协调器初始化

  1. 的ViewController
  2. 视图模型
  3. 我在上面发布的Coordinator类中。我们可以使用相同的start()函数来调用Web服务,如下所示。

    func start() {
        let storyboard = UIStoryboard(name: "Users", bundle: nil)
        if let vc = storyboard.instantiateViewController(withIdentifier: "list") as? UsersListController {
            let uDs = UserDataService(pClient:APIClient())
            uDs.getUserDetails { (response, status) in
                if (status == APIClient.APIResponseStatus.Success) {
                    if let resArrray = response as? [User] {
                        var viewModel = UsersListViewModel.init(userList: resArrray)
                        viewModel.delegate = self as UsersListViewModelDelegate
                        viewModel.veiwController = vc
                        vc.viewModel = viewModel
                        vc.coordinationDelegate = self as CoordinationDelegate
                        let nav = UINavigationController.init(rootViewController: vc)
                        self.window.rootViewController = nav
                    }
                } else {
                    //error alert
                }
            }
        }
    }
    

    最好在Coordinator类中调用Web服务调用。因为根据响应调用Web服务后我们可以控制视图导航。如果响应成功,我们可以创建一个ViewController类并加载它。否则我们可以加载错误弹出窗口。与此同时,我们可以花足够的时间进行Web服务调用,并将这些数据填充到viewModel。

    基于我通过互联网找到的内容,我使用MVVM-C架构实现了一个示例项目。我在GitHub中托管了它。您可以在here中找到它。

    通过引用此poroject,您可以清楚地了解如何使用MVVM-C模式实现视图导航,如何调用Web服务,如何从数据中填充viewModel等。

答案 2 :(得分:2)

在建筑方面,没有银弹。 牢记这一点MVVM-C是最干净,易于测试和模块化的模式之一,所以你继续使用它是很棒的。

您可以自由定制架构以满足您的要求。 话虽如此,考虑到您当前的设计,我认为最好创建一个Service类,称之为WebService。该课程将在协调员的监督下执行网络操作。协调员将

  1. Init WebService
  2. 执行网络通话
  3. 使用获取的数据初始化ViewModel(或指示ViewModel处理失败的网络呼叫)