【问题标题】:Start NSURLConnection requests serially串行启动 NSURLConnection 请求
【发布时间】:2014-09-18 01:50:27
【问题描述】:

我正在遍历一个包含少量字符串的数组,并为每个字符串向 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];                

}

【问题讨论】:

  • 有什么问题??? “我遇到的问题是我的 NSURLConnection 是使用标准异步调用设置的。这导致请求不会阻塞任何后续请求。”???
  • 嘿@gran33,我只想在收到第一个响应时才开始第二个连接..但是这里发生的事情是,请求是并行发出的
  • 这是一个类型错误...看看我更新的编辑
  • 好的,看我的下一个答案...
  • @Ranjit - 考虑递归解决方案。

标签: ios nsurlconnection


【解决方案1】:

我为您的问题想到了 2 个解决方案:

  1. AFNetworking - 你可以使用AFNetworking 并在成功块中维护一个计数器。计数器将对请求进行计数,当所有请求完成后,将执行您的下一个任务。

  2. GCD - Dispatch Groups - Grand Central Dispatch 为您提供组或请求的选项,并在最后(当所有请求完成时)做某事。为此,你需要阅读很好的教程(“Ray Wenderlich”的第二部分。如果你不熟悉 GCD,请跳到教程第一部分)。

无论如何,使用您上面的代码无法完成您的任务。你没有任何在请求结束时运行的异步块。

编辑:

使用 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);
}];

【讨论】:

  • hello @gran33 谢谢,我不想在完成所有请求后做一些任务,例如,假设我的数组计数是 4,那么当我在循环内运行时,它将发出 4 个请求,所以在这里面,我只想阻止其他 3 个请求,直到第一个请求完成并做出响应,依此类推
  • m8?..你能告诉我你理解了什么,什么没有......这样我可以更好地解释你。
  • m8 = mate ;) 我不明白这一点:“所以在这里面我只想阻止其他 3 个请求,直到第一个请求完成响应等等”
  • 好吧,让我解释一下,我有一个包含几个字符串的数组,每个字符串我必须通过单独的请求传递。所以我正在运行循环并发出 4 个请求并以 JSON 格式传递字符串.所以当我发送第一个请求的第一个字符串时,它会返回一个响应,所以对于第二个请求,我应该从第一个响应中发送一些值,依此类推......但目前发生的事情是调用在之后立即触发另一个不等待上一个请求的响应。
  • 嘿@gran,这是在进行同步调用吗?我没有用过AFNetworking,所以我需要先学习一下。如果我删除了 for 循环,我怎么知道要发出多少个请求?
【解决方案2】:

一个简单的方法是使用递归。创建一个发送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;
}

【讨论】:

  • 你好@danh 谢谢你的回答,正如你所说我的代码做同样的事情,但我正在使用循环,因为每次我发送新的 json。 JSON 数据随每个请求而变化
  • 请发布每次json如何变化。当前发布的代码显示了相同的变量,finalJSON 每次都被序列化。它在循环中改变吗?几个小时后回到我的办公桌……
  • @Ranjit - 仍然不确定 如何 json 更改,但编辑答案假设它确实如此。您应该能够弄清楚如何每次更改它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
相关资源
最近更新 更多