Ios 使用NSURLSession等待HTTP请求的响应-目标C
现在我正在开发一个小类,它有一个发送POST请求的方法。此方法用于返回ResponseModel(基本上有两个IVAR:代码、消息),此模型将从response映射。 我正在使用Ios 使用NSURLSession等待HTTP请求的响应-目标C,ios,objective-c,cocoa-touch,request,Ios,Objective C,Cocoa Touch,Request,现在我正在开发一个小类,它有一个发送POST请求的方法。此方法用于返回ResponseModel(基本上有两个IVAR:代码、消息),此模型将从response映射。 我正在使用dataTaskWithRequest:urlRequest completionHandler:方法。像这样: + (void)sendPOSTRequest1:(id)data withResponse:(void (^) (ResponseModel * data) )taskResponse { NSEr
dataTaskWithRequest:urlRequest completionHandler:
方法。像这样:
+ (void)sendPOSTRequest1:(id)data withResponse:(void (^) (ResponseModel * data) )taskResponse {
NSError *error = nil;
NSMutableURLRequest * urlRequest = [self getRequestObject];
[urlRequest setHTTPMethod:@"POST"];
NSData * requestData = [self encodeAndEncrypt:data];
[urlRequest setHTTPBody:requestData];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session
dataTaskWithRequest:urlRequest
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
ResponseModel * responseModel = [NSKeyedUnarchiver
unarchivedObjectOfClass:[ResponseModel class]
fromData:data
error:&error];
taskResponse(responseModel);
}];
[dataTask resume];
}
并按以下方式调用该方法:
DummyModel * dummy = [[DummyModel alloc] init];
__block ResponseModel * result = [[ResponseModel alloc] init];
[HTTPRequest sendPOSTRequest1:dummy withResponse:^(ResponseModel *data) {
result = data;
NSLog(@"data %@",data);
}];
// It`s not sure that the asyncronous request has already finished by this point
NSLog(@"POST result : %@",result);
我的问题是,我不想在回调块中执行代码,因为我需要等待响应以返回ResponseModel,而实现该模型的人可以接收模型并制作其他内容。
我一直在研究使用NSURLConnection,因为它有一种执行同步请求的方法,但现在它已被弃用,所以我一直在想:这是一种我可以使用代码中的内容等待响应的方法吗?您可以使用GCD实现如下同步请求: swift代码
public static func requestSynchronousData(请求:URLRequest)->数据?{
var数据:数据?=nil
让信号量:DispatchSemaphore=DispatchSemaphore(值:0)
让task=URLSession.shared.dataTask(with:request,completionHandler:{
中的taskData,错误->()
数据=任务数据
如果data==nil,则让error=error{print(error)}
信号量
})
task.resume()
_=信号量。等待(超时:.distantFuture)
返回数据
}
目标C代码
+ (NSData *)requestSynchronousData:(NSURLRequest *)request {
__block NSData * data = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable taskData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"%@", error);
}
data = taskData;
dispatch_semaphore_signal(semaphore);
}];
[task resume];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return data;
}
可以使用dispatch\u async处理块内的UI交互
DummyModel * dummy = [[DummyModel alloc] init];
__block ResponseModel * result = [[ResponseModel alloc] init];
[HTTPRequest sendPOSTRequest1:dummy withResponse:^(ResponseModel *data) {
result = data;
dispatch_async(dispatch_get_main_queue(), ^{
// handle some ui interaction
});
NSLog(@"data %@",data);
}];
不,你总是不想等待。无论谁调用您的
sendPOSTRequest
方法,都应该采用与此处完全相同的异步模式(例如,完成块等)。我知道,如果你把它变成一个只返回值的同步方法,感觉会非常明智和简单,但它几乎总是与你应该做的完全相反。而且,正如您所指出的,您也不想使用不推荐的NSURLConnection
。新API不提供同步方法是有原因的,所以接受异步模式。嗨,@Rob,谢谢你的回答。那么,既然您提到了附加到这个异步模式,是否仍然可以在块内处理一些UI交互(当调用方法时),以便向用户检索信息?是的,您可以在传递给sendPOSTRequest
的完成处理程序块中这样做。唯一的技巧是,您只想阻止将ivar和UI更新发送回主队列,例如dispatch\u async(dispatch\u get\u main\u queue(),^{…})代码>