我循环遍历包含少量字符串的数组,并为每个字符串向Web服务器发出请求 数组中的字符串。
我希望在将后续请求发送到服务器之前完全处理每个请求。因为每个请求都会向我发送一个响应,我将在下一个请求时发送,等等。
我遇到的问题是我的NSURLConnection是使用标准异步调用设置的。这导致请求不阻止任何后续请求。但是我需要在第一次完成之前阻止循环中的其他请求。
请求URL始终相同,只有JSON数据随循环中的每个请求而变化。 这是我的代码
for (int i = 0; i < array.count; i++)
{
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:finalJSON options:NSJSONWritingPrettyPrinted error:&error];
if (!jsonData) {
NSLog(@"Error creating JSON object: %@", [error localizedDescription]);
}
NSString *url = [NSString stringWithFormat:@“abc.com/folders”];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setValue:APIKEY forHTTPHeaderField:@"X_API_KEY"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonData];
//I am adding all connections to NSDictionary so that later I can process request.
NSURLConnection *connection = [self connectionForRequest:request];
[connection start];
}
答案 0 :(得分:1)
我想到了解决问题的两种解决方案:
AFNetworking - 你可以使用AFNetworking
并在成功块中维护一个计数器。计数器将对请求进行计数,完成所有操作后,将执行下一个任务。
GCD - Dispatch Groups - Grand Central Dispatch为您提供制作小组或请求的选项,并在最后(当所有请求完成时)执行某些操作。为此,你需要阅读精彩的教程(“Ray Wenderlich”的第2部分。如果你不熟悉GCD,请跳到教程的第1部分)。
无论如何,上面的代码U无法完成你的任务。你没有在请求结束时运行的任何异步块。
修改强>
使用AFNetworking:
你必须首先删除你的for循环,然后这样做:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo": @"bar"};
[manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { // HERE u can do your second request which uses the first response
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters_new = <USE_YOUR_DATA_FROM_responseObject>;
[manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { // HERE u can do your third request which uses the first and second response
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
答案 1 :(得分:0)
一种简单的方法是使用递归。创建一个发送url连接的方法,并在连接完成后调用自身再次发送它。
这是解决方案的关键:制作一个可以递归调用的方法,该方法可以发送请求并收集结果。通过在完成块中递归调用自身,此方法可以确保每个请求在上一个请求完成后开始...
// note - edited per the comments to get a new NSURLRequest each time
- (void)makeRequests:(NSInteger)count
results:(NSMutableArray *)results
completion:(void (^)(NSError *))completion {
// complete recursion
if (count == 0) return completion(nil);
NSURLRequest *request = [self nextRequest];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error) {
[results addObject:data];
[self makeRequests:count-1 results:results completion:completion];
} else {
completion(error);
}
}];
}
要调用它,请分配一个包含结果的数组......
- (void)makeManyRequests {
NSMutableArray *resultsArray = [NSMutableArray array];
[self makeRequests:10 results:resultsArray completion:^(NSError *error) {
NSLog(@"done. results are %@", resultsArray);
}];
}
编辑 - 它在OP中不清楚这个请求每次都会如何变化,但听起来你已经弄明白了。这只是您最初在自己的方法中发布的代码。这是一个好主意,因此您的代码可以清楚地了解每次它如何形成不同的JSON有效负载......
- (NSURLRequest *)nextRequest {
id finalJSON = // your app supplies...
// somehow, this changes each time nextRequest is called
NSString *APIKEY = // your app supplies
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:finalJSON options:NSJSONWritingPrettyPrinted error:&error];
if (!jsonData) {
NSLog(@"Error creating JSON object: %@", [error localizedDescription]);
}
// your request creation code, copied from the OP
NSString *url = [NSString stringWithFormat:@"abc.com/folders"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setValue:APIKEY forHTTPHeaderField:@"X_API_KEY"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonData];
return request;
}