參考資料
1.MVVM-維基百科
2.MVVM with RxSwift
3.RxSwift
4.RxSwift 學習指導
5.Moya
5.Codable
實現
這裡只解釋我對MVVM的理解,不再對RxSwift、Moya、Codable、MVVM做過多的敘述,相信Google會讓你知道的更多。
一、目錄結構
二、網路請求
1、相同格式資料的處理
對於Json的資料返回會有一個統一的返回格式
我們公司的Json格式,這三個欄位是鐵打不會變的,改變的只是data的資料。
{
code:Int,
data:[],
message:String
}
複製程式碼
練習使用的是豆瓣的一個介面 ("https://api.douban.com/v2/movie/top250")
class ReponseData<T: Codable>: Codable {
var count: Int?
var start: Int?
var total: Int?
var subjects: T?
}
複製程式碼
3.對Moya的封裝
Moya官方有一個和RxSwfit對接的擴充套件也可以直接使用哪個;
Json轉Model使用的Codable。
(1)Moya URL的配置檔案
Moya對URL的配置
import Foundation
import Moya
enum APIConfig {
case top
}
extension APIConfig: TargetType {
var sampleData: Data {
return "{}".data(using: .utf8)!
}
var task: Task {
return .requestPlain
}
var headers: [String : String]? {
return nil
}
var baseURL: URL {
return URL.init(string: "https://api.douban.com/v2/movie/")!
}
var path: String {
switch self {
case .top:
return "top250"
}
}
var method: Moya.Method {
switch self {
case .top:
return .get
}
}
}
複製程式碼
(2)Request封裝
func request <Element: Codable> (config: APIConfig) -> Observable<ResponseResult<Element>> {
return Observable.create({[weak self] (observable) -> Disposable in
let provider = MoyaProvider<APIConfig>()
let callBack = provider.request(config, completion: { (responseResult) in
switch responseResult {
case let .success(response):
do {
let decoder = JSONDecoder()
let data = try decoder.decode(ReponseData<Element>.self, from: response.data)
let subjects = data.subjects
let result = (subjects == nil) ? ResponseResult.empty : ResponseResult.succeed(data: subjects!)
observable.onNext(result)
}catch let error {
self?.requestError(message: error.localizedDescription)
observable.onNext(ResponseResult.failed(message: error.localizedDescription))
}
case let .failure(error):
self?.requestError(message: error.localizedDescription)
observable.onNext(ResponseResult.failed(message: error.localizedDescription))
}
})
return Disposables.create {
callBack.cancel()
}
})
}
複製程式碼
錯誤這樣處理是為了一些彈框的統一處理,且使用物件也獲得錯誤資訊可以做一些特殊處理。
三、Model
它只對各種資料和業務進行處理然後更新ViewModel;
不要含有任何UIKit類.
class Model: NSObject {
public func getData() -> Observable<ResponseResult<[Subjects]>> {
return HttpClient().request(config: APIConfig.top)
}
}
複製程式碼
四、View
包含ViewController、View、storyboard檔案,view是對業務是無感的,只做介面展示和使用者互動。
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet private weak var tableView: UITableView!
private var viewModel: ViewModel = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
viewModel.getData {[weak self] (status) in
self?.tableView.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.getItemCount()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TopTableViewCell = tableView.dequeueReusableCell(withIdentifier: "TopTableViewCell", for: indexPath) as! TopTableViewCell
cell.title.text = viewModel.getBindData(index: indexPath.row).title.value
return cell
}
}
複製程式碼
五、ViewModel
協調View和Model、資料的儲存。
class ViewModel: NSObject {
private var model = Model()
private var list = [Subjects]()
private var errorMessage: String = ""
func getData(callBack: @escaping (_ result: RequestStatus) -> Void) {
model.getData().subscribe(onNext: {[weak self] (result) in
switch result {
case .empty:
callBack(.empty)
case .succeed(let data):
self?.list = data
callBack(.succees)
case .failed(let errorMessage):
self?.errorMessage = errorMessage
callBack(.failed)
}
}).disposed(by: rx_disposeBag)
}
func getItemCount() -> Int {
return list.count
}
func getBindData(index: Int) -> BindingData {
return BindingData.init(list[index].title)
}
// 獲取網路錯誤資訊
func getErrorMessage() -> String {
return errorMessage
}
}
複製程式碼
以上是我對MVVM的理解,每個人對MVVM都有自己不同的理解,有什麼疑問或者問題或者好的建議歡迎指正。 專案地址
謝謝觀看