看下界面, 這是類似于索引的頁面, 只不過木有右側索引條的布局. 如果想了解通訊錄索引的,請移步iOS - 高仿通訊錄之商品索引排序搜索.
提供思路如下:
- 分析界面及接口
- 用 MVC 設計模式來實現(其實核心點都在下面5)
- 創建內外層 Model 并綁定兩者 Model
- 兩者 Cell 布局的實現 (便于后期界面的快速更改)
- 在外層控制器內進行邏輯操作并請求數據的分區及每個分區行數的處理. 5.1 創建一個保存數據的數組timeList, 這個數組是外層列表數組(分區時間數組) 5.2 拿到數組后, 就可以考慮分區數目及當前分區下 cell 數目 5.3 創建header的界面及數據 5.4 找到相對應的分區去帶回內層數組
- 跳轉控制器內層數組的傳值簡單實現.
Step1. 分析界面及接口
首先我們先分析這個界面: 很明顯這是一個 tableView 的多分區多cell的布局. 這樣就好辦許多,截取一個分區來做說明.
很明顯的能看出來, 這必須只能是 Model 套 Model 了. 分析下接口:
##Step2. 用 MVC 設計模式來實現. 大致思路有了,那我們接著該整理 MVC 了. 簡單來說, 就是創建兩套 MVC: 外層盤點記錄的 MVC 與 內層盤點詳情的 MVC(其中內層的還包括外層盤點記錄下的每個當前分區下的記錄 cell 詳情). 看起來是兩套 MVC, 由于我們內層的兩個數組里字典數據是一樣的模型, 我就共用了一套內層 M, 其實是三部分的交錯使用. 看個點擊分區跳轉到盤點詳情的 MVC 界面:
##Step3. 創建內外層 Model 并綁定兩者 Model 由于只提供思路,就只放核心部分代碼. 先創建內層的 子Model(YYPRecordDetailsModel)就和一般正常的 Model 創建一樣就好,
// 時間
@property (nonatomic, copy) NSString *dotime;// 商品名稱
@property (nonatomic, copy) NSString *commodityName;// 商品金額
@property (nonatomic, assign) float commodityAmt;// 實際盤點數量
@property (nonatomic, assign) NSInteger inventoryNum;// 庫存數量
@property (nonatomic, assign) NSInteger stockNum;
復制代碼
接著創建外層的 一級Model(YYPInventoryRecordModel), 除了幾個基本單元素外, 兩個內層數組是子 Model 不要忘了要放進去.
// 詳情全部數據
@property (nonatomic, strong) NSArray *inventoryList;// 虧盈數據
@property (nonatomic, strong) NSArray *inventoryList2;
復制代碼
最后在外層 Model 的. m 里實現兩者的綁定.
+ (NSDictionary *)objectClassInArray {return @{@"inventoryList" : [YYPRecordDetailsModel class], @"inventoryList2" : [YYPRecordDetailsModel class]};
}
復制代碼
##Step4. 兩者 Cell 布局的實現 頁面都是根據產品和 UI 確定, 我們單獨寫UITableViewCell, 好處就是便于后期界面的快速更改.
可以根據自己的界面來寫. 我這里就記錄下 Model 賦值. 一定切記,選擇相對應的 Model. 我這里展示分區下的 cell 就相對應的是子Modle.
// model賦值
- (void)setModel:(YYPRecordDetailsModel *)model {_model = model;// 商品名稱self.commodityName.text = [NSString stringWithFormat:@"%@", model.commodityName];// 單價self.commodityAmt.text = [NSString stringWithFormat:@"¥%.2f", model.commodityAmt];// 盈虧if (model.inventoryNum >= model.stockNum) {self.result.textColor = YYPGrayTitleColor;if (model.inventoryNum > model.stockNum) {self.result.text = [NSString stringWithFormat:@"+%ld", (model.inventoryNum - model.stockNum)];} else {self.result.text = @"0";}} else if (model.inventoryNum < model.stockNum) { // 虧self.result.textColor = YYPRedTitleColor;self.result.text = [NSString stringWithFormat:@"-%ld", (model.stockNum - model.inventoryNum)];}
}
復制代碼
##Step5. 在外層控制器內進行邏輯操作并請求數據的分區及每個分區行數的處理.
其實這里就是重點核心部分了!我要劃重點啦~
####5.1 看盤點記錄界面, 就是一個TableView, 那么我們創建一個保存數據的數組timeList, 這個數組是外層列表數組(分區時間數組).
@property (nonatomic, strong) NSMutableArray *timeList;
復制代碼
- (NSMutableArray *)timeList {if (!_timeList) {_timeList = [NSMutableArray array];}return _timeList;
}
復制代碼
**PS: 切記!!!**千萬不要再創建內層數組,容易把自己繞糊涂, 有了外層數組,需要內層數組數據時是可以通過外層數組 timeList 去獲取的.譬如行數據:model.inventoryList2[indexPath.row]
####5.2 拿到數組后, 就可以考慮分區數目及當前分區下 cell 數目
#pragma mark - Table view data source- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {self.tableView.mj_footer.hidden = self.timeList.count == 0;return self.timeList.count;
}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {YYPInventoryRecordModel *model = self.timeList[section];return model.inventoryList2.count;
}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {YYPInventoryRecordDetailCell *detailCell = [YYPInventoryRecordDetailCell cellWithTableView:tableView];if (self.timeList.count) { // 有時候傳值為nilYYPInventoryRecordModel *model = self.timeList[indexPath.section];YYPRecordDetailsModel *detailModel = model.inventoryList2[indexPath.row];detailCell.model = detailModel;}return detailCell;
}#pragma mark - UITableViewDelegate- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {return YYPInventoryRecordDetailCellHeight;
}
復制代碼
####5.3 這個時候盤點記錄的 cell詳情出來了, 接著考慮header的界面及數據. 在viewForHeaderInSection
里創建
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section ;
復制代碼
賦值取當前一級 Model 下字段: [[_timeList objectAtIndex:section] valueForKey:@"dotime"]];
dotime.text = [NSString stringWithFormat:@"%@", [[_timeList objectAtIndex:section] valueForKey:@"dotime"]];
復制代碼
分區Header內容也是由外層 Model 賦值的, 返回每個分區的內容self.timeList[section]
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {return self.timeList[section];
}
復制代碼
####5.4 由于我們還有下個跳轉頁面,同時還是取當前接口數據, 這個時候我們就要找到相對應的分區去跳轉即可.
在cell 點擊跳轉相對來說方便的多,因為這個有系統方法didSelectRowAtIndexPath
.只需要找到相對應分區self.timeList[indexPath.section]
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {YYPInventoryRecordModel *model = self.timeList[indexPath.section];YYPRecordDetailsController *vc = [[YYPRecordDetailsController alloc] init];vc.inventoryList = model.inventoryList;[self.navigationController pushViewController:vc animated:YES];
}
復制代碼
若是header 上也要實現按鈕跳轉, 可以在viewForHeaderInSection
方法里的按鈕上加個標記與header的分區section一致, 然后找到相對應分區**self.timeList[sender.tag]**就好.
inIcon.tag = section;
復制代碼
實現跳轉方法
- (void)btnClick:(UIButton *)sender {// 用 tag 來標記sectionYYPInventoryRecordModel *model = self.timeList[sender.tag];YYPRecordDetailsController *vc = [[YYPRecordDetailsController alloc] init];vc.inventoryList = model.inventoryList;[self.navigationController pushViewController:vc animated:YES];
}
復制代碼
####5.5 最后就是請求了.
拿到最外層的數組數據就好.
[weakSelf.timeList removeAllObjects];
NSArray *currentPageArray = [YYPInventoryRecordModel loadInventoryRecordInfoFromJson:json[@"data"]];
[weakSelf.timeList addObjectsFromArray:currentPageArray];
復制代碼
至于上拉加載更多數據/下拉刷新新數據 及 網絡不佳狀態重新加載獲取請求這些都是按自己項目需求添加的. 這里就不一一展示了.
##Step6. 跳轉控制器內層數組的傳值簡單實現. 這其實就是一個簡單的正常的 MVC. 就是不需要請求接口,就是正向傳值帶回來一個數組. .h 里露出一個屬性便于傳值.
// 詳情全部數據
@property (nonatomic, strong) NSArray *inventoryList;
復制代碼
在. m 里創建一個保存接收數據的可變數據
// 詳情全部數據
@property (nonatomic, strong) NSMutableArray *goodList;
復制代碼
需要加載inventoryList數據帶回到goodList.
#pragma mark - 懶加載- (NSMutableArray *)goodList {if (!_goodList) {_goodList = [NSMutableArray array];[_goodList addObjectsFromArray:_inventoryList];}return _goodList;
}
復制代碼
簡單的Table view data source方法:
#pragma mark - Table view data source- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {return self.goodList.count;
}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {YYPRecordDetailsCell *cell = [YYPRecordDetailsCell cellWithTableView:tableView];if (self.goodList.count) { // 有時候傳值為nilYYPRecordDetailsModel *model = self.goodList[indexPath.row];cell.model = model;}return cell;
}
復制代碼
這個時候,完整測試下效果吧:
如果需要看訂單詳情頁那種Model 套 Model 的請移步: Model套Model之iOS模型閑聊