异步请求改写为同步请求

1  使用nsurl se s si o n 进行异步请求,使用callback进行回调。但是有时候为了改写一些方法,需要在异步回调完成之后再进行后续操作,这个时候就需要用到信号量来进行同步请求的改写。具体例子如下:

异步:

- (void)HOAWithParameters:(NSMutableDictionary*)param

                callback:(void(^)(id))callback

{

    NSMutableString *baseURLString = [[NSMutableString alloc] initWithString:HOA_URL_PRO];

    [baseURLStringappendString:HOA_AUTH];


    NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:baseURLString]];

    [reqsetHTTPMethod:@"POST"];


    NSMutableDictionary *md5Dic = [[NSMutableDictionary alloc] initWithDictionary:param];

    NSData *paramData = [NSJSONSerialization dataWithJSONObject:md5Dic options:NSJSONWritingPrettyPrinted error:nil];

    NSString *paramString = [[NSString alloc] initWithData:paramData encoding:NSUTF8StringEncoding];


    req = [selfsetHeader:paramjsonString:paramStringrequest:req];

    [reqsetHTTPBody:paramData];


    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:_opQueue];

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {


            if(error) {

                callback(nil);

            }

            else{

                NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];

                callback(dataDic);

            }


    }];

    [dataTaskresume];

}


调用这个异步方法的方法:

-(void)validateAuthTokenWithCallback:(void(^)(BOOLisSucceeded,id_Nullableresponse))callback{

    [[CMIOTHOAApi shareInstance] setServerPro:self.isServerPro];

    NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:self.authToken,@"token", nil];

    [[CMIOTHOAApi shareInstance] HOAWithParameters:[params mutableCopy] callback:^(id response){

        if(response!=nil&& [[responseobjectForKey:@"resultCode"]intValue] ==0) {

             callback(YES,@"鉴权成功");

        }else{

              //NSString *errdes = [NSString stringWithFormat:@"鉴权失败 %@",self.authToken];

            callback(NO, response);

        }

    }];

}

采用 dispatch_semaphore_t match_sema = dispatch_semaphore_create(0); dispatch_semaphore_signal(match_sema);dispatch_semaphore_wait(match_sema, DISPATCH_TIME_FOREVER);来进行改写为同步方法的方法如下:

-(BOOL)validateAuthToken{

    [[CMIOTHOAApi shareInstance] setServerPro:self.isServerPro];

    dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    __blockBOOLisvalid =NO;

    dispatch_semaphore_t match_sema = dispatch_semaphore_create(0);

    NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:self.authToken,@"token", nil];

    dispatch_async(quene, ^{

        [[CMIOTHOAApi shareInstance] HOAWithParameters:[params mutableCopy] callback:^(id response){

            if(response!=nil&& [[responseobjectForKey:@"resultCode"]intValue] ==0) {

                isvalid =YES;

                dispatch_semaphore_signal(match_sema);

            }else{

                isvalid =NO;

                dispatch_semaphore_signal(match_sema);

            }

        }];

    });


    dispatch_semaphore_wait(match_sema, DISPATCH_TIME_FOREVER);



    returnisvalid;

}


注意一点:   dispatch_semaphore_signal(match_sema); 和 dispatch_semaphore_wait(match_sema, DISPATCH_TIME_FOREVER); 必须要在不同的线程才不会照成死锁,否者一直调用不到 dispatch_semaphore_wait(match_sema, DISPATCH_TIME_FOREVER);方法。  

如果nsurl se s si o n  的da ta task 的回调放到了主线程,那么一定会死锁。 解决方案就是去掉回调的主线程代码。 

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容