GCD,Block和动态加载混合
来源:互联网 发布:人工智能服务器 编辑:程序博客网 时间:2024/05/20 18:00
场景解析:
1.消费记录页面需要两个接口去服务器请求数据
2.加载成功和失败共有一个小菊花View
问题1:
使用dispatch_group_async:
_queue=dispatch_queue_create("getData", DISPATCH_QUEUE_SERIAL);
_group = dispatch_group_create();
dispatch_group_async(self.group, self.queue,^{
//获取price
//动态加载
__block SEL sel =NSSelectorFromString(@"getPrice");
if ([self respondsToSelector: sel])SuppressPerformSelectorLeakWarning([self performSelector: sel withObject:nil]);
});
dispatch_group_async(self.group, self.queue,^{
//获取order
__block SEL sel =NSSelectorFromString(@"getOrder");
if ([selfrespondsToSelector: sel]) SuppressPerformSelectorLeakWarning([selfperformSelector:sel withObject: nil]);
});
dispatch_group_notify(self.group,self.queue, ^{
//更新UI
NSLog(@"%@",self.recordOfConsumptionArray);
// [self.recordOfConsumptionTableView reloadData];
});
A:不管怎么处理,第一次网络请求是没有数据的NSLog(@"%@",self.recordOfConsumptionArray);
打印为空。
于是把queue改成_queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);可是结果还是一样。
本来多个数据请求使用dispatch_group_async是一个非常好的方法选择,可是问题来了,加载成功和失败共有一个小菊花View,使用异步小菊花不知道怎么释放了,以及dispatch_group_notify里面的block回调不到数据。
B:这个问题的解决根源还是要靠线程管理
使用:dispatch_queue_create("getData",DISPATCH_QUEUE_SERIAL)和dispatch_sync,
通过debug数据程序跟踪,完美的解决
dispatch_sync(self.queue, ^{
//获取price
//动态加载
__block SEL sel = NSSelectorFromString(@"getPrice");
if ([self respondsToSelector: sel])SuppressPerformSelectorLeakWarning([self performSelector: selwithObject: nil]);
});
dispatch_sync(self.queue, ^{
//获取order
__block SEL sel = NSSelectorFromString(@"getOrder");
if ([self respondsToSelector: sel])SuppressPerformSelectorLeakWarning([self performSelector:selwithObject: nil]);
});
可是问题还有一个就是AFNetWorking的success: failure:回调方法,这可能是数据一时还没有获取到,因为线程分之了,马上执行了dispatch_group_notify的block,可是数据的获取还在success:回调方法里面,由于并发的原因,导致了在[weakSelf.recordOfConsumptionTableViewreloadData];更新数据的时间点,数据还没有到,只因为它们不在一条线程以及一个队里面。
当然我试过:
dispatch_sync(self.queue, ^{
//获取price
//动态加载
__block SEL sel = NSSelectorFromString(@"getPrice");
if ([self respondsToSelector: sel])SuppressPerformSelectorLeakWarning([self performSelector: selwithObject: nil]);
});
dispatch_barrier_async(dispatch_get_main_queue(), ^{
//获取order
__block SEL sel = NSSelectorFromString(@"getOrder");
if ([self respondsToSelector: sel])SuppressPerformSelectorLeakWarning([selfperformSelector:selwithObject: nil]);
});
dispatch_barrier_async(self.queue, ^{
NSLog(@"%@", self.recordOfConsumptionArray);
[self.recordOfConsumptionTableView reloadData];
});
可是还是解决不了。问题的根源就是共有一个view,这个view的状态更改不能在子线程里面处理。
问题2:
动态加载:performSelector may cause a leak becauseits selector is unknown"警告
http://www.tuicool.com/articles/iu6zuu ios之"performSelector may cause a leak because itsselector is unknown"警告原因及其解决办法
// 使用宏忽略警告 performSelector may causea leak because its selector is unknown"警告原因及其解决办法
#defineSuppressPerformSelectorLeakWarning(Stuff) \
do { \
_Pragma("clang diagnosticpush")\
_Pragma("clang diagnosticignored \"-Warc-performSelector-leaks\"") \
Stuff; \
_Pragma("clang diagnosticpop")\
} while (0)
//动态加载
__block SEL sel = NSSelectorFromString(@"getPrice");
if ([self respondsToSelector: sel])SuppressPerformSelectorLeakWarning([self performSelector: selwithObject: nil]);
原因
在ARC模式下,运行时需要知道如何处理你正在调用的方法的返回值。这个返回值可以是任意值,如 void , int , char , NSString , id 等等。ARC通过头文件的函数定义来得到这些信息。所以平时我们用到的静态选择器就不会出现这个警告。因为在编译期间,这些信息都已经确定。
问题3:
capturing 'self' strongly in this block is likely to lead a retain cycle
为了封装方法和使用block回调:
typedef void (^getURLBlock)(NSDictionary *dic);
@property (nonatomic, copy) getURLBlock urlBlock;
- (NSDictionary *)getURLData: (NSString *)url parameters:(NSDictionary *)parameters
{
__weak __typeof(self)weakSelf = self;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST: url parameters: parameters success: ^(AFHTTPRequestOperation *operation, id successObject){
__weak NSData *data =operation.responseData;
__weak NSDictionary *dic = [NSJSONSerializationJSONObjectWithData: data options:NSJSONReadingMutableContainers error: nil];
weakSelf.urlBlock(dic);
}failure: ^(AFHTTPRequestOperation *operation, NSError *error){
[weakSelf makeToast: ERR_NETWORK];
[DejalBezelActivityView removeViewAnimated: YES];
[weakSelf.pullToRefreshtableViewReloadFinishedAnimated:YES];
}];
return [NSDictionary dictionary];
}
//请求price
- (void)getPrice
{
__weak NSDictionary *dic = [CommonUtil getObjectFromUD:@"userInfo"];
if([CommonUtil isEmpty:dic[@"user_id"]]){
return;
}
__weak NSString *url = [RequestHelpergetFullUrl:@"/api/user/myorder" Host:REQUEST_HOST];
__weak NSDictionary *parameters = [NSDictionarydictionaryWithObjectsAndKeys: dic[@"user_id"], @"user_id", nil];
[DejalBezelActivityView activityViewForView: self.view];
__block SEL sel =NSSelectorFromString(@"getURLData:parameters:");
if ([self respondsToSelector: sel])SuppressPerformSelectorLeakWarning([self performSelector: selwithObject: url withObject: parameters]);
//解决循环引用的bug capturing 'self'strongly in this block is likely to lead a retain cycle
__weak __typeof(self)weakSelf = self;
self.urlBlock = ^(NSDictionary *dic){
NSInteger code = [[dic objectForKey: @"code"]integerValue];
if (code == 1) {
//操作成功
//循环引用的bug
// self.total_priceLabel.text =[NSString stringWithFormat: @"%0.2f", [[dic objectForKey:@"total"] doubleValue]];
// self.save_priceLabel.text =[NSString stringWithFormat: @"%0.2f", [[dic objectForKey:@"save"] doubleValue]];
weakSelf.total_priceLabel.text = [NSStringstringWithFormat: @"%0.2f", [[dic objectForKey: @"total"]doubleValue]];
weakSelf.save_priceLabel.text = [NSStringstringWithFormat: @"%0.2f", [[dic objectForKey: @"save"]doubleValue]];
}else{
[weakSelf makeToast: [dic objectForKey: @"message"]];
[DejalBezelActivityView removeViewAnimated: YES];
}
};
可是问题又来了:多个网络请求,block回调方法出不去就异步请求了,这回到的上面的问题了;没办法只有再来一个block
- GCD,Block和动态加载混合
- 初识GCD和block
- GCD和Block 使用
- GCD和Block
- Block和GCD介绍
- iOS 之GCD和Block
- GCD Block
- GCD/Block
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- GCD(Grand Central Dispatch)和Block 使用总结
- GCD(Grand Central Dispatch)和Block 使用-浅析
- GCD(Grand Central Dispatch)和Block 使用-浅析
- SecureCRT 修改文件夹蓝色字体
- HBase compact
- 主工程与依赖的module工程R文件消失
- 在PowerShell中Write-Host/Output的区别
- 2016.05.08培训日记
- GCD,Block和动态加载混合
- Java图形界面开发—简易记事本
- java基础类型的使用选择
- 2016.05.15培训日记
- Js中的天坑----JS:parseInt("08")和“09”返回0
- NOIP2013 D1 T3 货车运输 树上倍增lca+Kruskal
- iOS9的3D Touch
- C++ const限定符详细说明
- ECSHOP account_log,pay_log,user_account 三个表的用途与区别 用户余额的数据库表和函数