多线程异步获取获取服务端数据
2018-09-13 本文已影响52人
苍茫的天涯
多线程异步获取获取服务端数据,全成功以后再返回主线程进行操作的简单方法记录
这次遇到项目是一个基金类的项目,所以经常会遇到一个页面需要调用到好几个接口的情况,如何能又符合客户的需求,又符合用户的体验就是个比较有意思的事儿了,这里基本就是用两种办法来针对不同情况
需要优先展示UI 而后显示数据的情况
这种情况下我用的方法是直接跳转,然后在viewDidLoad
或viewWillAppear
异步调用所有的接口,在接口成功返回的时刷新对应的cell或section
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self loadNetWork];
}
- (void)loadNetWork {
// 接口1
[LoadNetWork loadRequest1:@{} callback:^(NSDictionary *response) {
self.data1 = response;
}];
// 接口2
[LoadNetWork loadRequest2:@{} callback:^(NSDictionary *response) {
self.data2 = response;
}];
// 接口3
[LoadNetWork loadRequest3:@{} callback:^(NSDictionary *response) {
self.data3 = response;
}];
}
- (void)setData1:(NSDictionary *)data1 {
_data1 = data1;
[_tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}
- (void)setData2:(NSDictionary *)data2 {
_data2 = data2;
[_tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:1 inSection:1],[NSIndexPath indexPathForRow:1 inSection:2],[NSIndexPath indexPathForRow:1 inSection:3]] withRowAnimation:UITableViewRowAnimationNone];
}
- (void)setData3:(NSDictionary *)data3 {
_data3 = data3;
[_tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
}
这样就能轻松做到先展示页面而后随着数据加载而不断刷新cell的需求了,这也是一个提高tableview性能的好办法【刷新的时候只刷新对应的section或者row】
额外说一下UITableViewRowAnimation这个动画的含义
typedef NS_ENUM(NSInteger, UITableViewRowAnimation) {
UITableViewRowAnimationFade, //淡入淡出
UITableViewRowAnimationRight, //从右滑入
UITableViewRowAnimationLeft, //从左滑入
UITableViewRowAnimationTop, //从上滑入
UITableViewRowAnimationBottom, //从下滑入
UITableViewRowAnimationNone, // 无动画
UITableViewRowAnimationMiddle, // available in iOS 3.2. attempts to keep cell centered in the space it will/did occupy
UITableViewRowAnimationAutomatic = 100 // 自动动画,很难描述,但是动作很大,而且效果不错,可以自行试试
};
关于必须获取所有数据后才进行跳转或者所有页面的展示
这种情况也比较常见,是需要先将好几个接口的数据全加载好以后才能进行主线程操作,在很多场景下都有需求。主要使用的办法是利用Dispatch Group来实现。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self loadData];
}
- (void)loadData {
// 这里最好加上加载状态
[SVProgressHUD show];
dispatch_group_t group = dispatch_group_create();
//接口1
dispatch_group_enter(group);
[self loadData1IsScu:^(BOOL isScu) {
dispatch_group_leave(group);
}];
//接口2
dispatch_group_enter(group);
[self loadData2IsScu:^(BOOL isScu) {
dispatch_group_leave(group);
}];
//接口3
dispatch_group_enter(group);
[self loadData3IsScu:^(BOOL isScu) {
dispatch_group_leave(group);
}];
dispatch_group_notify(group,dispatch_get_main_queue(), ^(){
NSLog(@"===全部执行完毕");
[self.tableView reloadData];
// 在这儿把加载状态结束
[SVProgressHUD dismissWithDelay:0.1];
});
}
#pragma mark - 数据请求
- (void)loadData1IsScu:(void(^)(BOOL isScu))requestisScu {
[LoadNetWork loadRequest1:@{} callback:^(NSDictionary *response) {
self.data1 = response;
requestisScu(YES);
}];
}
- (void)loadData2IsScu:(void(^)(BOOL isScu))requestisScu {
[LoadNetWork loadRequest1:@{} callback:^(NSDictionary *response) {
self.data2 = response;
requestisScu(YES);
}];
}
- (void)loadData3IsScu:(void(^)(BOOL isScu))requestisScu {
[LoadNetWork loadRequest3:@{} callback:^(NSDictionary *response) {
self.data3 = response;
requestisScu(YES);
}];
}
这样就能做到在三个data都调用成功以后再进行操作的效果了,同时,如果有错误的返回或者其他需求只要改变requestisScu()的返回就行了,可以随机应变