MVVM Example
用MVVM的设计做一个简单的UITableview
首先是Model
我这里用一个rest api “https://api.tvmaze.com/shows/216?embed=seasons&embed=episodes”
把我想要的properties用struct 列出来,这样在一会破解json的时候比较方便使用
为了方便使用,我这里只需要 _embedded 里的episodes, episodes里有每一集的名字,哪一集,id, 上映时间,简介等信息
这里我会先用playground去测试我写的properties是否正确,还有URLsession是否写的正确
import UIKit
struct object: Decodable {
let _embedded: embeddedContainer
}
struct embeddedContainer: Decodable {
let episodes: [episodesContainer]
}
struct episodesContainer: Decodable {
let number: Int
let name: String
let summary: String
}
let urlString = "https://api.tvmaze.com/shows/216?embed=seasons&embed=episodes"
let url = URL(string: urlString)!
URLSession.shared.dataTask(with: url) { (data, _, _) in
guard let data = data else { return }
let json = try? JSONDecoder().decode(object.self, from: data)
print(json)
}.resume()
这里显示格式正确以后,就可以直接复制到model, 然后把URLsession单独写一个function 放到NetworkController的文件里
func loadURL(url: String, completion: @escaping(Data?, URLResponse?, Error?) -> Void) {
guard let url = URL(string: url) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
completion(data, response, error)
}.resume()
}
因为URLsession是一个closure,那就需要做一个escaping,这样在function的return之后, closure也会被call
Model就直接用刚刚在playground里写好的复制进去就好了
import UIKit
struct object: Decodable {
let _embedded: embeddedContainer
}
struct embeddedContainer: Decodable {
let episodes: [episodesContainer]
}
struct episodesContainer: Decodable {
let number: Int
let name: String
let summary: String
}
ViewModel
ViewModel 里会是一些business logic,这样做优点是会比较容易测试,跟一般的Controller 也会lightweight一些,这里我会用到dependency injection,把所有的function写进一个protocol里,这样一会使用起来会比较方便,也可以把viewModel当成一个单独的property来使用。这里我需要首先把url里的东西放到一个var里,我还需要一个episodes的container返回我所需要的信息,还需要这个var的count,方便一会在UITableView返回count的值。 这里我还写了一个updateCallback,这样在一会tableView里就会知道我的episode的值变了,tableView就会进行更新
ViewController
在所有我需要的条件就具备以后,这里我就可以直接写一个var,给予这个它viewModelProtocol的property。同时我也需要写一个updateCallback,在我的episodeContainer得到值以后,我就可以reload我的tableView,这样tableView上就可以显示每一集的名字。在updateCallBack里,我需要一个
DispatchQuenue,把它的执行放在main thread上面。
总结:
相比于MVC,MVVM可以更清晰的看到背后的business logic,这样方便之后的测试,controller也不会有太多的code同时也方便我们更新以后可能会用到的信息。