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 的回调放到了主线程,那么一定会死锁。 解决方案就是去掉回调的主线程代码。
网友评论