如何将数据从ViewModel层传递到视图层

时间:2017-02-19 01:26:50

标签: ios swift

我不知道如何将数据从我的viewModel传递到我的视图,最后在视图中显示数据,我的视图模型类是:

class MainViewModel {

    let sessionController: SessionController
    weak var mainViewCoordinator: MainViewCoordinator?
    public var fakeUsers: [User]?

    init(sessionController: SessionController = SessionController()) {
        self.sessionController = sessionController
    }

    func viewDidLoad() {
        Service.instance.execute(resource: User.fake) { (result) in
            print("\n result \(result)\n")
            self.fakeUsers = result.value
        }
    }
}

我使用的是Unbox Swift JSON解码器,打印结果是和User对象的数组是这样的:

([
  User(id: "5851ac2615801e2348e4ea07", 
       birthDate: "2016-09-17T07:22:09.985Z", 
       msisdn: "912 065 979", 
       email: "rosa_bravo@yahoo.com", 
       profileImageUrl: "https://s3.amazonaws.com/...", 
       repPoints: 41607, 
       created: "2016-12-14T20:31:34.185Z", 
       displayName: "Victoria Escobedo"), 
  User(id: "5851ac2615801e2348e4ea09", 
       birthDate: "2016-05-06T11:38:23.678Z", 
       msisdn: "958842030", 
       email: "francisca_barrios@gmail.com", 
       profileImageUrl: "https://s3.amazonaws.com/...", 
       repPoints: 71408, 
       created: "2016-12-14T20:31:34.198Z", 
       displayName: "Gonzalo Rascón"), 
   User(id: "5851ac2615801e2348e4ea08", 
        birthDate: "2016-05-29T18:12:32.423Z", 
        msisdn: "905534639", 
        email: "ral0@gmail.com", 
        profileImageUrl: "https://s3.amazonaws.com/...", 
        repPoints: 24164, 
        created: "2016-12-14T20:31:34.195Z", 
        displayName: "Ramiro Dueñas"),
   ...
])

我想将结果传递给View Layer(MainViewController)以在表格视图单元格中显示每个用户:

类MainViewController:UIViewController,UITableViewDataSource {

@IBOutlet var tableview:UITableView!
var viewModel: MainViewModel = MainViewModel()

override func viewDidLoad() {
    super.viewDidLoad()
    viewModel.viewDidLoad()
    self.tableview?.reloadData()
    self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Action", style: .plain, target: self, action: #selector(action))
}

func action() {
    viewModel.userDidSelectItem(identifier: "xxxx")
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return viewModel.fakeUsers?.count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "fakeUserObjectCell") as! MainTableViewCell
    cell.fakeUserObject = viewModel.fakeUsers?[(indexPath as NSIndexPath).row]
    return cell
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "detailSegue" {
        let detailMainViewController = segue.destination as! DetailMainViewController
        if let indexPath = tableview.indexPath(for: sender as! MainTableViewCell) {
            detailMainViewController.id = viewModel.fakeUsers?[(indexPath as NSIndexPath).row].id
        }
    }
}

}

我知道我必须实施self.tableview?.reloadData()来展示假冒用户,但我不知道如何传递数据并最终显示出来。

2 个答案:

答案 0 :(得分:1)

Service.instance.execute()中的以下viewModel.viewDidLoad()是异步调用。它尚未完成提取,您有来电self.tableview?.reloadData()因此可能会产生0行。

我建议将ViewModel viewDidLoad()更改为完成调用

func viewDidLoad() {
    Service.instance.execute(resource: User.fake) { (result) in
        print("\n result \(result)\n")
        self.fakeUsers = result.value
    }
}

像这样:

func loadUsers(completion: () -> ()) {
    Service.instance.execute(resource: User.fake) { (result) in
        print("\n result \(result)\n")
        self.fakeUsers = result.value
        completion()
    }
}

因此,在MainViewControllerviewDidLoad中,您可以在准备就绪时将呼叫更改为reloadData()

override func viewDidLoad() {
    super.viewDidLoad()
    viewModel.loadUsers {
        self.tableview?.reloadData()
    }
    self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Action", style: .plain, target: self, action: #selector(action))
}

答案 1 :(得分:0)

  • public var fakeUsers: [User]?
  • 中声明公开变量MainViewModel
  • 更新fakeUsers MainViewModel
  • 中的viewDidLoad()
  • fakeUsers
  • 中不需要MainViewController var {li> numberOfRowsInSection MainViewController现在返回由fakeUsers设置的MainViewModel计数,如:


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {   
    return viewModel.fakeUsers?.count ?? 0
}

同样,对于cellForRowAt indexPath:

编辑:

Service.instance.execute API调用不会立即返回,但如果确实如此,则应使用新内容更新数据数组&该表要求刷新。
但现在问题是我们无法table访问MainViewModel
因此,当Service提取完成后,我们可以notify MainViewController执行table.reloadData()
我希望你能提出这个代码的代码,你需要从这里开始:

class MainViewModel {
    ...

    func viewDidLoad() {
        Service.instance.execute(resource: User.fake) { (result) in
            print("\n result \(result)\n")
            self.fakeUsers = result.value
            // Edu, the table refresh notification is to be fired from here
        }
    }
}