ViewModel功能 1: 對網絡請求操做進行封裝統一處理。對ViewController進行瘦身。網絡
1.咱們先來實現一個 tableview 列表,而後列表裏的數據是經過網絡請求去獲取。atom
2.思考下,若是不用 ViewModel的時候,咱們的寫法是 把網絡請求的封裝的get方法寫到 ViewController 裏面,而後去處理成功或者失敗的回調方法。把數據源在ViewController裏定義好,而且在回調裏進行添加或者修改刪除....操做處理。spa
例子:.net
[[YYWHttpClient shareInstanceClient] sendGetRequestWith:SEARCH_CAR parameter:parameter response:^(id JSONData, NSError *error, NSURLSessionDataTask *dataTask) { 索引
}];rem
回調方法裏可能會作一些:get
a.對數據源進行操做的代碼,it
例如:下拉刷新的操做請求的話,在ViewModel裏 直接對 原始數據進行所有刪除,而後去加入新的返回過來的數據.io
if (operationType == RCarListRefreshTypeDropDown) {table
[self.carSource removeAllObjects];
}
for (CarInfo *carInfo in carList) {
[self.carSource addObject:carInfo];
}
b.在請求前能夠會對參數進行一些驗證,
好比 你可能根據角色去請求不一樣的網絡請求,好比管理員可能要請求兩個請求,而普通員工只用拿到一個請求。
包括參數裏 有哪些參數若是爲 空或者 0的話 默認傳什麼參數...之前在VC裏寫的一些判斷什麼的均可以寫在這裏。
若是一個ViewController的請求過多的話,那麼它自身的代碼行數也會愈來愈多,並且管理修改起來也不是很方便,
因此這個時候 能夠用 ViewModel來處理這一部分的功能。而且把數據源定義也能夠用在ViewModel裏去定義,在ViewController裏 直接返回 self.viewModel.carSource.count 以及顯示其中的內容。
3.好比作了 上拉加載更多,或者下拉刷新的操做,這個時候要去進行網絡請求,咱們這個時候就能夠直接
在ViewModel裏定義一個方法,方法名字就是你當前所作的操做,好比:
- (void)refreshCarListWithOperation:(CarListRefreshType)operationType success:(void (^)(void))successBlock error:(void (^)(CarHTTPCode))errorBlock {}
在ViewController裏就能夠在 下拉刷新和加載的時候直接用 self.viewModel去調用這個方法,而後傳入是刷新仍是加載更多的類型。當這個回調完成後,在裏面進行ViewController裏的刷新和加載更多控件的結束: [myRefresh endRefreshing]; 在viewModel裏的方法裏去作 網絡請求和對數據源進行處理 還有就是要傳的參數處理。
在ViewModel裏 寫一個 回調block ,去處理,當網絡請求成功後 須要作的變動,好比單獨刪除/更新狀態 某一條,所有刷新,.... 當ViewModel裏的網絡請求成功或者失敗的時候 去作一些處理。例子:
/// 車輛列表數據源變動回調,攜帶變動的類型及索引(全量更新時索引不存在)
@property (nonatomic, copy) void(^CarListChanged)(RCarListChangedType type, NSIndexPath * _Nullable indexPath);
而後ViewModel裏網絡請求失敗或成功回調後加入下面這行代碼, 根據須要來進行 調用這個block 傳出去給vc須要的一些信息,
self.carListChanged ? self.carListChanged(RCarListChangedTypeRefresh, indexPath) : nil
在ViewController的 viewmodel懶加載初始化的時候 寫好 收到 block調用 回調裏須要作什麼:
[_viewModel setCarListChanged:^(CarListChangedType type, NSIndexPath * _Nullable index) {
[weakSelf updateCarListWithType:type index:index];
}];
- (void)updateCarListWithType:(CarListChangedType)type index:(NSIndexPath *)indexPath {
if (type == CarRoomListChangedTypeReloadAll) {
[self.carListView reloadData];
} else if (type == CarRoomListChangedTypeRefresh) {
[self.carListView reloadItemsAtIndexPaths:@[indexPath]];
} else if (type == CarListChangedTypeDelete) {
[self.carListView deleteItemsAtIndexPaths:@[indexPath]];
}