日常用的刷新用是開源的MJRefresh,這個刷新庫想必也是不少開發者比較熟悉的一個庫,做者採用繼承的方式,不一樣的層次有不一樣的功能與UI展現,用起來簡潔,方便。bash
MJ爲UIScrollView類寫了類別,給UIScrollView增長了mj_header
(下拉刷新)和mj_footer
(上拉加載更多)兩個關聯對象。 MJ做者李明傑老師的示例用法以下:網絡
__weak typeof(self) weakSelf = self;
self.tableView.mj_header = [MJRefreshHeader headerWithRefreshingBlock:^{
[weakSelf refreshAction];//這裏能夠作請求網絡等操做。
}];
刷新的操做結束後,調用下邊方法,結束刷新
[self.tableView.mj_header endRefreshing];
複製代碼
__weak typeof(self) weakSelf = self;
self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
[weakSelf footerRefreshAction];//請求更多數據
}];
//能夠根據請求的結果來以不一樣的方式結束刷新。
[self.tableView.mj_footer endRefreshing];
[self.tableView.mj_footer endRefreshingWithNoMoreData];
複製代碼
以上只是示例,MJ中做者提供來多種不一樣UI和交互的header和footer供你們選擇使用。ui
日常這樣直接按照做者的Demo示例用能夠,可是我的總以爲不太好。就想着可以封裝下(主要是懶,想省點事)。atom
先說下基本的需求:一個tableView的列表,每頁請求20(注:不一樣的公司可能不一樣的每頁條數,這裏只是舉例)條數據,下拉刷新的時候是從新請求第一頁的數據,上拉加載更多的時候是請求下一頁數據。若是下一頁數據仍是20條,則認爲還有數據,將footr以正常的狀態結束刷新。再次上拉加載的時候,還會正常請求下一頁的數據。 若是加載出來的數據少於一頁的數據條數(20條),那麼就認爲沒有更多數據了,這時就將footer以沒有更多數據的狀態結束刷新,再進行上拉加載的時候,將不起做用。spa
我想要的效果是,我外部調用的時候,我只想知道觸發去請求刷新和加載更多的時機, 其它的都不想管。code
本人目前的實現是:給UITableView寫了一個類別(UICollectionView同理。UIScrollView也能夠進行下拉刷新,只不過是不用上拉加載更多了)。寫了兩個方法,分別是下拉刷新和上拉加載的調用。同時增長了兩個關聯對象:每頁的數據條數和一個上拉加載更多後的footer的設置回調的block。 示例代碼以下:orm
#define WeakSelf __weak typeof(self) weakSelf = self;
typedef void(^FooterConfigBlock)(NSInteger newDataCount);
typedef void(^RefreshActionBlock)(FooterConfigBlock footerConfig);
@interface UITableView (Refresh)
/**
每頁的數據條數
*/
@property (nonatomic,strong)NSNumber *pageCount;
/**
設置footer的回調
*/
@property (nonatomic,copy)void(^footerConfigBlock)(NSInteger newCount);
/**
header的刷新
@param refreshBlock 刷新的回調,回調block裏有個"FooterConfigBlock"的參數,外部調用的時候能夠將請求下拉的數據的條數傳進來,讓方法裏邊對footer進行設置。eg:若是下拉刷新都沒有數據的話,就能夠直接將不要footer。
*/
- (void)normalHeaderRefreshingActionBlock:(RefreshActionBlock)refreshBlock;
/**
footer的刷新加載更多
@param footerRefreshBlock 加載更多的回調。回調block裏有個"FooterConfigBlock"的參數,外部調用的時候能夠將請求下拉的數據的條數傳進來,讓方法裏邊對footer進行設置。eg:若是上拉加載返回的數據小於每頁的設置條目數量,則認爲數據已經加載完畢,能夠將footer設置爲沒有更多數據的狀態。
*/
- (void)backNormalFooterRefreshingActionBlock:(RefreshActionBlock)footerRefreshBlock;
@end
@implementation UITableView (Refresh)
#pragma mark --關聯對象----------------
- (void)setPageCount:(NSNumber *)pageCount
{
objc_setAssociatedObject(self, @selector(setPageCount:), pageCount, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSNumber *)pageCount
{
return objc_getAssociatedObject(self, @selector(setPageCount:));
}
- (void)setFooterConfigBlock:(void (^)(NSInteger))footerConfigBlock
{
objc_setAssociatedObject(self, @selector(setFooterConfigBlock:), footerConfigBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (void (^)(NSInteger))footerConfigBlock
{
return objc_getAssociatedObject(self, @selector(setFooterConfigBlock:));
}
#pragma mark --header刷新----------------
- (void)normalHeaderRefreshingActionBlock:(RefreshActionBlock)refreshBlock
{
//若是外部調用的時候不設置每頁的數據條目數量pageCount。這裏設置一個默認值。
self.pageCount = [self.pageCount integerValue] > 0 ? self.pageCount : @(20);
WeakSelf
//將外部的block給關聯對象賦值,若是外部須要內部進行footer和header結束刷新的處理的話,能夠傳block進來。
self.footerConfigBlock = ^(NSInteger newCount) {
[weakSelf handleEndRefreshing:newCount];
};
self.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
refreshBlock(weakSelf.footerConfigBlock);
}];
}
#pragma mark --footer刷新----------------
- (void)backNormalFooterRefreshingActionBlock:(RefreshActionBlock)footerRefreshBlock
{
//同理設置一個默認的每頁數據條目
self.pageCount = [self.pageCount integerValue] > 0 ? self.pageCount : @(20);
WeakSelf
self.footerConfigBlock = ^(NSInteger newCount) {
[weakSelf handleEndRefreshing:newCount];
};
self.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
footerRefreshBlock(weakSelf.footerConfigBlock);
}];
}
- (void)handleEndRefreshing:(NSInteger)count
{
if (self.mj_header.isRefreshing) {
[self.mj_header endRefreshing];
[self.mj_footer endRefreshing];
}
if (count < [self.pageCount integerValue]) {
[self.mj_footer endRefreshingWithNoMoreData];
}else{
[self.mj_footer endRefreshing];
}
}
#pragma mark --結束刷新-----
//若是外部想本身處理結束刷新,能夠爲tabelView添加的其它結束刷新的方法。
- (void)beginRefreshing
{
if (!self.mj_header) return;
[self.mj_header beginRefreshing];
}
- (void)endRefrehing
{
if (self.mj_header) {
[self.mj_header endRefreshing];
}
if (self.mj_footer) {
[self.mj_footer endRefreshing];
}
}
@end
複製代碼
外部的調用以下:對象
- (void)configTableView
{
WeakSelf
[self.tableView normalHeaderRefreshingActionBlock:^(FooterConfigBlock _Nonnull footerConfig) {
weakSelf.page = 1;
//上拉刷新觸發請求第一頁數據。
[weakSelf requestData:^(NSInteger count) {
weakSelf.dataCount = count;
[weakSelf.tableView reloadData];
//請求成功後將數據的條數回調給tableView,讓tableVie本身處理footer的設置
footerConfig(count);
} failCallBack:^{
[weakSelf.tableView endRefrehing];
}];
}];
[self.tableView backNormalFooterRefreshingActionBlock:^(FooterConfigBlock _Nonnull footerConfig) {
[weakSelf requestData:^(NSInteger count) {
weakSelf.dataCount += count;
[weakSelf.tableView reloadData];
//請求成功後將數據的條數回調給tableView,讓tableVie本身處理footer的設置
footerConfig(count);
} failCallBack:^{
[weakSelf.tableView endRefrehing];
}];
}];
[self.tableView beginRefreshing];
}
- (void)requestData:(void(^)(NSInteger count))successCallBack failCallBack:(void(^)(void))failCallBack
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self.page > 5) {
successCallBack(0);
}else{
successCallBack(20);
}
self.page += 1;
});
}
複製代碼
以上只是本身的簡單封裝示例,MJRefresh提供了多種header和footer,能夠根據業務或產品的要求自定義並封裝適合本身的使用代碼。繼承
以上是本人的一些使用總結,若有錯誤,還請批評指正。謝謝!!!ci