以下方法使用AFNetworking向Web服务发送请求,并且(成功时)对响应进行操作。 AFNetworking以异步方式执行请求,并使用块来成功或失败。所以发送请求的方法看起来像这样(简化):
- (void)sendRequestForConnector:(NSString *)connector
success:(void (^)(NSData *responseXml))success
failure:(void (^)(NSError *error))failure
{
AFHTTPRequestOperation *operation = [self HTTPRequestOperationForConnector:connector];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
[self handleSuccessForConnector:connector response:[operation responseData]];
success([operation responseData]);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
[self handleFailureForConnector:connector error:error];
failure(error);
}
[operation start];
}
在另一个类中,此方法用于多次调用Web服务。当前一个呼叫成功时,下一个呼叫完成。此方法看起来像这样(为简洁省略了故障块):
- (void)import
{
[client sendRequestForConnector:@"cities" success:^{
[client sendRequestForConnector:@"categories" success:^{
[client sendRequestForConnector:@"categoryTranslations" success:^{
[client sendRequestForConnector:@"products" success:^{
[client sendRequestForConnector:@"productTranslations" success:^{
[self finishImport];
}];
}];
}];
}];
}];
}
这很有效,但是可以看出,每个webservice调用都会添加另一个嵌套的成功块处理程序。在我看来,必须有一个更好的方法来做到这一点,但我想不出一个。
最好,我想在下一次调用之前等待之前的调用完成,并使用像GCD之类的东西来异步调用整个导入方法。但是,AFNetworking并非旨在进行同步呼叫。
非常欢迎任何有关如何实现这一目标的想法。或者我目前的解决方案是否可行?
答案 0 :(得分:2)
我处于相同的情况,我需要等待响应,并且需要在完成上次上传后调用ws进行上传,
有几种方法可以做到这一点
1)您可以使用dispatch_group
并在完成所有操作后通知。
2)使用create semaphores逐个调用ws
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
dispatch_semaphore_t test = dispatch_semaphore_create(0);
for (NSUInteger i = 0; i < self.uploadDocument.count; ++i) {
// My custom method with block which call ws
[self uploadMultipleImagesUsingAFNetworkingMultipartFormatWithDocumentId:[[self.uploadDocument objectAtIndex:i] valueForKey:kDocument_DocumentId] andIndex:i withCompletionBlock:^(id responseObj, NSError *error) {
// Your Logic
dispatch_semaphore_signal(test);
}];
dispatch_semaphore_wait(test, DISPATCH_TIME_FOREVER);
// Here comes when your all ws finish
dispatch_async(dispatch_get_main_queue(), ^{
[self.tblUpload reloadData];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
});
}
答案 1 :(得分:1)
您可以查看octokit
。他们将AFNetworking与Mantle和ReactiveCocoa相结合 - 使用ReactiveCocoa轻松,干净地进行链接。
答案 2 :(得分:0)
我建议你看一下这个答案Better asynchronous control flow with Objective-C blocks
建议使用一些自定义解决方案来解决此问题。
答案 3 :(得分:0)
我面临同样的问题,一直在考虑引入PromiseKit&amp; AFNetworking-PromiseKit一段时间了。但我终于放弃了,并提出了一个简单而有点克服的解决方案,
所以我介绍了一个名为“step”的属性,其主要目的是为了它。然后对于每个异步调用完成时,它需要标记其步骤。然后kvo方法将整个过程移动到下一步,即 kvo方法进行流量控制。
例如,你的sendRequestForConnector:@“cities”将是第1步,@“categories”是第2步,@“categoryTranslations”是第3步,@“products”是第4步......在每次成功结束时block将步骤设置为自己的值。所以kvo会知道这一步已经完成,需要调用下一个异步方法。
kvo方法监督并控制整个过程。
compositeTemplates
到目前为止它符合我的目的,我的代码看起来更清晰。
答案 4 :(得分:-1)
如果要进行同步调用,则只需使用NSString的“stringWithContentsOfURL:”方法。因此,只需在循环中使用此代码循环遍历NSURL的NSArray。
NSError* error = nil;
NSString* htmlSource = [NSString stringWithContentsOfURL:theNSURL encoding:NSUTF8StringEncoding error:&error];
if (error) {
// handle error
}
// parse htmlSource