GCD,Block和动态加载混合

来源:互联网 发布:人工智能服务器 编辑:程序博客网 时间:2024/05/20 18:00
GCD,Block和动态加载混合
  由于这几天分析了SDWebImageAFNetWorking,了解到GCDBlock的好处,于是今天尝试把原来项目食趣的代码利用GCDBlock和动态加载改了,那么问题来了。
 

 

场景解析:

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_DEFAULT0);可是结果还是一样。

本来多个数据请求使用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: selwithObjectnil]);

       

       

    });

   

    dispatch_sync(self.queue, ^{

        //获取order

        __block SEL sel = NSSelectorFromString(@"getOrder");

        if ([self respondsToSelector: sel])SuppressPerformSelectorLeakWarning([self performSelector:selwithObjectnil]);

    });

可是问题还有一个就是AFNetWorkingsuccess: failure:回调方法,这可能是数据一时还没有获取到,因为线程分之了,马上执行了dispatch_group_notifyblock,可是数据的获取还在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: selwithObjectnil]);

原因

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 (nonatomiccopygetURLBlock 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 errornil];

       

       

           

           weakSelf.urlBlock(dic);

           

        

       

    }failure: ^(AFHTTPRequestOperation *operation, NSError *error){

       

        [weakSelf makeToastERR_NETWORK];

        [DejalBezelActivityView removeViewAnimatedYES];

        [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 activityViewForViewself.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 removeViewAnimatedYES];

           

        }

       

    };

可是问题又来了:多个网络请求,block回调方法出不去就异步请求了,这回到的上面的问题了;没办法只有再来一个block

1 0
原创粉丝点击