一 设置刷新方法
// 添加刷新控件
- 先将footer隐藏
/**
* 添加刷新控件
*/
- (void)setupRefresh {
self.userTableView.header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewUsers)];
self.userTableView.footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreUsers)];
self.userTableView.footer.hidden = YES;
}
二 网络请求结束在回调方法中不管成功失败都要结束刷新
// 结束刷新
[self.userTableView.header endRefreshing];
成功获取到数据还要检测footer状态 判断是否全部加载完毕
// 让底部控件结束刷新
[self checkFooterState];
检测footer状态方法
/**
* 时刻监测footer的状态
*/
- (void)checkFooterState {
XMGRecommendCategory *rc = XMGSelectedCategory;
// 每次刷新右边数据时, 都控制footer显示或者隐藏
self.userTableView.footer.hidden = (rc.users.count == 0);
// 让底部控件结束刷新
if (rc.users.count == rc.total) { // 全部数据已经加载完毕
[self.userTableView.footer noticeNoMoreData];
} else { // 还没有加载完毕
[self.userTableView.footer endRefreshing];
}
}
每次数据加载完毕 刷新tableview都会调用这个方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
所以在这个方法中判断footer状态
// 监测footer的状态
[self checkFooterState];
三 点击cell发送网络请求 快速点击多个cell时候 网络请求处理
首先,在代理方法中停止之前的刷新动作
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 结束刷新
[self.userTableView.header endRefreshing];
[self.userTableView.footer endRefreshing];
}
若是有数据 就显示数据 刷新tableview 若是没数据就先刷新表格 清空上次的数据 再进行刷新请求数据
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 结束刷新
[self.userTableView.header endRefreshing];
[self.userTableView.footer endRefreshing];
XMGRecommendCategory *c = self.categories[indexPath.row];
if (c.users.count) {
// 显示曾经的数据
[self.userTableView reloadData];
} else {
// 赶紧刷新表格,目的是: 马上显示当前category的用户数据, 不让用户看见上一个category的残留数据
[self.userTableView reloadData];
// 进入下拉刷新状态
[self.userTableView.header beginRefreshing];
}
}
五 同时快速切换点击的时候 对block中回调数据的处理
先定义参数属性
/** 请求参数 */
@property (nonatomic, strong) NSMutableDictionary *params;
- 在刷新方法中 设置完参数 用属性保存参数信息
// 请求参数
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"a"] = @"list";
params[@"c"] = @"subscribe";
params[@"category_id"] = @(rc.id);
params[@"page"] = @(rc.currentPage);
// 保存参数
self.params = params;
- 在回调block中通过参数判断 对数据进行处理
(多次网络请求 我们只要取最后一次请求,其余返回的数据放在相对应的模型中就好 不必展示)
// 不是最后一次请求
if (self.params != params) return;
- 不管返回成功失败 都需要处理 不然上次请求失败 此次请求中会展示错误toast,而实际上此次请求并没有错误
六 控制器销毁时候 撤销所有网络请求
- 网络加载慢的时候 用户可能退出控制器,此时若是请求完成在回调block中调用可能会引起崩溃,所以在销毁控制器的时候,撤销网络请求
- 先定义AFN manager属性
/** AFN请求管理者 */
@property (nonatomic, strong) AFHTTPSessionManager *manager;
- 懒加载
- (AFHTTPSessionManager *)manager {
if (!_manager) {
_manager = [AFHTTPSessionManager manager];
}
return _manager;
}
- 控制器销毁的时候调用
#pragma mark - 控制器的销毁
- (void)dealloc {
// 停止所有操作
[self.manager.operationQueue cancelAllOperations];
}
附上代码
#import "XMGRecommendViewController.h"
#import <AFNetworking.h>
#import <SVProgressHUD.h>
#import "XMGRecommendCategoryCell.h"
#import <MJExtension.h>
#import "XMGRecommendCategory.h"
#import "XMGRecommendUserCell.h"
#import "XMGRecommendUser.h"
#import <MJRefresh.h>
#define XMGSelectedCategory self.categories[self.categoryTableView.indexPathForSelectedRow.row]
@interface XMGRecommendViewController () <UITableViewDataSource, UITableViewDelegate>
/** 左边的类别数据 */
@property (nonatomic, strong) NSArray *categories;
/** 左边的类别表格 */
@property (weak, nonatomic) IBOutlet UITableView *categoryTableView;
/** 右边的用户表格 */
@property (weak, nonatomic) IBOutlet UITableView *userTableView;
/** 请求参数 */
@property (nonatomic, strong) NSMutableDictionary *params;
/** AFN请求管理者 */
@property (nonatomic, strong) AFHTTPSessionManager *manager;
@end
@implementation XMGRecommendViewController
static NSString * const XMGCategoryId = @"category";
static NSString * const XMGUserId = @"user";
- (AFHTTPSessionManager *)manager
{
if (!_manager) {
_manager = [AFHTTPSessionManager manager];
}
return _manager;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 控件的初始化
[self setupTableView];
// 添加刷新控件
[self setupRefresh];
// 加载左侧的类别数据
[self loadCategories];
}
/**
* 加载左侧的类别数据
*/
- (void)loadCategories {
// 显示指示器
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeBlack];
// 发送请求
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"a"] = @"category";
params[@"c"] = @"subscribe";
[self.manager GET:@"http://api.budejie.com/api/api_open.php" parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
// 隐藏指示器
[SVProgressHUD dismiss];
// 服务器返回的JSON数据
self.categories = [XMGRecommendCategory objectArrayWithKeyValuesArray:responseObject[@"list"]];
// 刷新表格
[self.categoryTableView reloadData];
// 默认选中首行
[self.categoryTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop];
// 让用户表格进入下拉刷新状态
[self.userTableView.header beginRefreshing];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
// 显示失败信息
[SVProgressHUD showErrorWithStatus:@"加载推荐信息失败!"];
}];
}
/**
* 控件的初始化
*/
- (void)setupTableView {
// 注册
[self.categoryTableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGRecommendCategoryCell class]) bundle:nil] forCellReuseIdentifier:XMGCategoryId];
[self.userTableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGRecommendUserCell class]) bundle:nil] forCellReuseIdentifier:XMGUserId];
// 设置inset
self.automaticallyAdjustsScrollViewInsets = NO;
self.categoryTableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
self.userTableView.contentInset = self.categoryTableView.contentInset;
self.userTableView.rowHeight = 70;
// 设置标题
self.title = @"推荐关注";
// 设置背景色
self.view.backgroundColor = XMGGlobalBg;
}
/**
* 添加刷新控件
*/
- (void)setupRefresh {
self.userTableView.header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewUsers)];
self.userTableView.footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreUsers)];
self.userTableView.footer.hidden = YES;
}
#pragma mark - 加载用户数据
- (void)loadNewUsers {
XMGRecommendCategory *rc = XMGSelectedCategory;
// 设置当前页码为1
rc.currentPage = 1;
// 请求参数
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"a"] = @"list";
params[@"c"] = @"subscribe";
params[@"category_id"] = @(rc.id);
params[@"page"] = @(rc.currentPage);
self.params = params;
// 发送请求给服务器, 加载右侧的数据
[self.manager GET:@"http://api.budejie.com/api/api_open.php" parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
// 字典数组 -> 模型数组
NSArray *users = [XMGRecommendUser objectArrayWithKeyValuesArray:responseObject[@"list"]];
// 清除所有旧数据
[rc.users removeAllObjects];
// 添加到当前类别对应的用户数组中
[rc.users addObjectsFromArray:users];
// 保存总数
rc.total = [responseObject[@"total"] integerValue];
// 不是最后一次请求
if (self.params != params) return;
// 刷新右边的表格
[self.userTableView reloadData];
// 结束刷新
[self.userTableView.header endRefreshing];
// 让底部控件结束刷新
[self checkFooterState];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if (self.params != params) return;
// 提醒
[SVProgressHUD showErrorWithStatus:@"加载用户数据失败"];
// 结束刷新
[self.userTableView.header endRefreshing];
}];
}
- (void)loadMoreUsers {
XMGRecommendCategory *category = XMGSelectedCategory;
// 发送请求给服务器, 加载右侧的数据
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"a"] = @"list";
params[@"c"] = @"subscribe";
params[@"category_id"] = @(category.id);
params[@"page"] = @(++category.currentPage);
self.params = params;
[self.manager GET:@"http://api.budejie.com/api/api_open.php" parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
// 字典数组 -> 模型数组
NSArray *users = [XMGRecommendUser objectArrayWithKeyValuesArray:responseObject[@"list"]];
// 添加到当前类别对应的用户数组中
[category.users addObjectsFromArray:users];
// 不是最后一次请求
if (self.params != params) return;
// 刷新右边的表格
[self.userTableView reloadData];
// 让底部控件结束刷新
[self checkFooterState];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if (self.params != params) return;
// 提醒
[SVProgressHUD showErrorWithStatus:@"加载用户数据失败"];
// 让底部控件结束刷新
[self.userTableView.footer endRefreshing];
}];
}
/**
* 时刻监测footer的状态
*/
- (void)checkFooterState {
XMGRecommendCategory *rc = XMGSelectedCategory;
// 每次刷新右边数据时, 都控制footer显示或者隐藏
self.userTableView.footer.hidden = (rc.users.count == 0);
// 让底部控件结束刷新
if (rc.users.count == rc.total) { // 全部数据已经加载完毕
[self.userTableView.footer noticeNoMoreData];
} else { // 还没有加载完毕
[self.userTableView.footer endRefreshing];
}
}
#pragma mark - <UITableViewDataSource>
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// 左边的类别表格
if (tableView == self.categoryTableView) return self.categories.count;
// 监测footer的状态
[self checkFooterState];
// 右边的用户表格
return [XMGSelectedCategory users].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.categoryTableView) { // 左边的类别表格
XMGRecommendCategoryCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGCategoryId];
cell.category = self.categories[indexPath.row];
return cell;
} else { // 右边的用户表格
XMGRecommendUserCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGUserId];
cell.user = [XMGSelectedCategory users][indexPath.row];
return cell;
}
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// 结束刷新
[self.userTableView.header endRefreshing];
[self.userTableView.footer endRefreshing];
XMGRecommendCategory *c = self.categories[indexPath.row];
if (c.users.count) {
// 显示曾经的数据
[self.userTableView reloadData];
} else {
// 赶紧刷新表格,目的是: 马上显示当前category的用户数据, 不让用户看见上一个category的残留数据
[self.userTableView reloadData];
// 进入下拉刷新状态
[self.userTableView.header beginRefreshing];
}
}
#pragma mark - 控制器的销毁
- (void)dealloc {
// 停止所有操作
[self.manager.operationQueue cancelAllOperations];
}
@end