2022.02.11更新:新增了最簡單、高效和最推薦的方法。
2020.05.25更新:對總結進行了詳細的補充。
傳統(tǒng)的上拉加載更多
在iOS的開發(fā)過程中淤击,如果用列表展示數據,此時一般的邏輯為上拉加載更多數據荣回,配合MJRefresh就是在滑動到最底部時遭贸,觸發(fā)加載更多的網絡請求。
滑動過程中預加載
如果希望體驗好一點心软,那么可以在滑動的過程中,加入一個預加載機制著蛙,具體的做法如下:
方法1(最簡單删铃、高效和最推薦):
使用MJRefresh
的特性(MJ大神已經替我們封裝好了,但是大多數人都不知道)踏堡,在設置TableVIew的MJRefreshAutoFooter
時猎唁,triggerAutomaticallyRefreshPercent
這個屬性默認是1,我們來看看源代碼中是怎么說的:
此時我們只需要一行代碼:
MJRefreshAutoFooter *footer = [MJRefreshAutoFooter footerWithRefreshingTarget:weakSelf refreshingAction:@selector(loadMore)];
footer.triggerAutomaticallyRefreshPercent = -20; //關鍵的一行代碼
self.tableView.mj_footer = footer;
將這個屬性設置為一個負數顷蟆,意思就是當控件的底部出現(xiàn)-20時就自動刷新诫隅,很明顯腐魂,-20的距離就代表還沒有滑動到底部,就觸發(fā)了刷新了逐纬,這樣便完成了我們的預加載的需求蛔屹。
方法2(自己計算實現(xiàn),不推薦了):
下滑(上拉)過程中豁生,對當前scrollView(tableView)的剩余可滑動距離(總滑動距離占可滑動距離的)比例進行判斷兔毒,如果小于(大于)某個設定值,那么就觸發(fā)網絡請求(加載更多數據)甸箱。
- 這樣做的好處顯而易見育叁,用戶不必再去多做一個上拉加載更多數據的操作了,如果我們需要展示的數據量非常大的話芍殖,那么此種加載方式可以節(jié)省用戶大量的操作時間豪嗽,大大提升了用戶的使用體驗。
下面是具體實現(xiàn)細節(jié)(此細節(jié)是針對上述方法2的)
方法2是作者之前自己研究出來的豌骏,但是后來發(fā)現(xiàn)MJ已經為我們實現(xiàn)了這么好的方法昵骤,就用不到了。有興趣的同學可以看看方法2的具體實現(xiàn):
1.我們需要在實現(xiàn)網絡請求的類中添加一個Bool屬性肯适,用來判定當前是否正在進行網絡請求变秦;
@property (nonatomic, assign) BOOL isLoadingDataBool; //是否正在請求數據
2.在scrollView的滑動代理方法中,處理預加載機制的邏輯
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (self.tableview.mj_footer.state == MJRefreshStateNoMoreData) {
// 沒有更多數據框舔,直接返回
return;
}
// 預加載的計算邏輯蹦玫,當滑動距離>80%目前剩余可滑動距離的時候,觸發(fā)預加載
CGFloat threshold = 0.8; //設定的比例值
CGFloat current = scrollView.contentOffset.y + ((scrollView.contentSize.height != scrollView.frame.size.height) ? scrollView.frame.size.height : 0); //當前滑動距離
CGFloat total = scrollView.contentSize.height; //總的可滑動距離
CGFloat ratio = current / total;
if (ratio >= threshold) { //滑動距離超過比例值
[self requestDataList:NO showHUD:NO]; //發(fā)起加載更多網絡請求
self.isLoadingDataBool = YES; //設置正在網絡請求狀態(tài)為YES(一定要寫在請求之后)
}
}
3.處理網絡請求
/// 發(fā)起網絡請求
/// @param isReloadBool 是否為刷新請求
/// @param isShowHUDBool 是否加載指示器
- (void)requestDataList:(BOOL)isReloadBool showHUD:(BOOL)isShowHUDBool {
if (self.isLoadingDataBool) {
// 當前正在請求刘绣,直接返回
return;
}
kWeakSelf(self);
[DZCXHTTP requestWithResulted:^(BOOL isSuccessed, NSDictionary *dataDic, NSString *errorMsg) {
kStrongSelf(self);
strongself.isLoadingDataBool = NO; //請求完成樱溉,設置正在請求的狀態(tài)為NO
}];
}
總結
這個預加載其實不難,但是有幾個細節(jié)的地方需要處理好:
1.第二步scrollView的代理方法中計算當前滑動時纬凤,一定要判斷當前的contenntSize是否等于scrollView的高度福贞,如果等于的話證明scrollView是剛剛開始滑動,還沒有過一屏的距離停士,此時在計算當前滑動的距離時挖帘,就不能加上scrollView的高度;
2.當滑動的比例值超出我們設定值的時候恋技,移動要先發(fā)起網絡請求拇舀,再設置正在網絡請求的狀態(tài)為YES,因為在網絡請求中會對該狀態(tài)進行判斷蜻底,如果為YES的話直接就return了骄崩;
3.在網絡請求的完成回調中,別忘記了將正在網絡請求的狀態(tài)改回為NO。