本文是寫給剛?cè)胄械男峦瑢W(xué)看界酒。
問題
在處理列表分頁時奇瘦,對于頁碼的管理很容易出bug蜂怎。一個常見的誤區(qū)是:在請求發(fā)起的同時對頁碼作了遞增操作楼吃,由此造成了如果請求過程中出現(xiàn)網(wǎng)絡(luò)異常演痒,或者無數(shù)據(jù)返回時亲轨,頁碼的這一次遞增就是無效的。
- 如果不處理鸟顺,再次進行上拉加載時惦蚊,會繼續(xù)對頁碼遞增,此時會造成之前請求失敗的那一頁數(shù)據(jù)缺失讯嫂。
- 如果說在發(fā)現(xiàn)請求異常時蹦锋,把頁碼減回去,會容易讓處理邏輯變得復(fù)雜欧芽,且一邊遞增一邊遞減莉掂,不可靠而且不推薦。
- 比較好的做法是千扔,只有在成功取到我們希望的那一頁數(shù)據(jù)時憎妙,再把頁碼作遞增库正,始終讓頁碼是指向未來要加載的那一頁。
示例
這里借助MJRefresh為TableView添加了頂部刷新和底部刷新:
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(onHeaderRefresh)];
self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(onFooterRefresh)];
無論是重新刷新還是加載更多厘唾,都不應(yīng)該知道頁碼的存在褥符,在它們的響應(yīng)方法角度看,只關(guān)心是否需要重置列表數(shù)據(jù)
/// 頂部刷新
- (void)onHeaderRefresh {
[self requestServerDataReset:YES];
}
/// 底部加載更多
- (void)onFooterRefresh {
[self requestServerDataReset:NO];
}
在數(shù)據(jù)請求方法里抚垃,統(tǒng)一管理頁碼喷楣。只有兩處對頁碼進行賦值,分別是重置列表時和成功取到一頁數(shù)據(jù)時:
- (void)requestServerDataReset:(BOOL)reset {
if (reset) {
self.page = 1;
}
self.title = [NSString stringWithFormat:@"正在請求第%@頁", @(self.page)];
[self generateServerDataWithPage:self.page finish:^(NSMutableArray<NSString *> *data) {
[self.tableView.mj_header endRefreshing];
[self.tableView.mj_footer endRefreshing];
if (reset) {
[self.dataSource removeAllObjects];
}
if (data && data.count) {
[self.dataSource addObjectsFromArray:data];
self.title = [NSString stringWithFormat:@"第%@頁:成功返回%@條", @(self.page), @(data.count)];
self.page ++;
}
else {
self.title = [NSString stringWithFormat:@"第%@頁:請求失敗或無數(shù)據(jù)", @(self.page)];
}
[self.tableView reloadData];
}];
}
另外是模擬服務(wù)響應(yīng)鹤树、返回數(shù)據(jù)的方法
/// 生成模擬數(shù)據(jù)铣焊,page從0開始
- (void)generateServerDataWithPage:(NSInteger)page finish:(void (^)(NSMutableArray<NSString *> *data))finish {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 模擬處理用時
sleep(1);
// 模擬網(wǎng)絡(luò)異常
static NSInteger flag = 0;
if (++flag % 2 == 0) {
NSLog(@"網(wǎng)絡(luò)異常!");
dispatch_async(dispatch_get_main_queue(), ^{
finish(nil);
});
return;
}
// 正常返回數(shù)據(jù)
NSInteger dataCount = 10;
NSMutableArray *arr = [NSMutableArray array];
for (NSInteger index = 1; index <= dataCount; index ++) {
[arr addObject:[NSString stringWithFormat:@"第%@頁,第%@條", @(page), @(index)]];
}
dispatch_async(dispatch_get_main_queue(), ^{
finish(arr);
});
});
}