发送一堆请求一个接一个

我需要发送100个networking请求到我的服务器一个接一个,并得到通知,当第100个完成。

我正在使用AFNetworking,正在考虑解决这个问题。 任何人都可以推荐我吗?

一些想法:

  1. 如果真的只是连续地(即一个接一个地)运行每个请求,你可以这样做:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init]; queue.maxConcurrentOperationCount = 1; NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"All operations done"); }]; for (NSInteger i = 0; i < operationCount; i++) { AFHTTPRequestOperation *operation = ... // create your operation here [completionOperation addDependency:operation]; [queue addOperation:operation]; } [queue addOperation:completionOperation]; 

    请注意,使用这样的操作队列提供的优点是,如果您需要,可以轻松取消该队列中的所有操作。

    如果执行这些命令的顺序非常重要,则可能需要在操作之间build立明确的依赖关系,例如:

     NSOperationQueue *queue = [[NSOperationQueue alloc] init]; queue.maxConcurrentOperationCount = 1; NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"All operations done"); }]; NSOperation *priorOperation = nil; for (NSInteger i = 0; i < operationCount; i++) { AFHTTPRequestOperation *operation = ... // create your operation here [completionOperation addDependency:operation]; if (priorOperation) [operation addDependency:priorOperation]; [queue addOperation:operation]; priorOperation = operation; } [queue addOperation:completionOperation]; 
  2. 对我来说,问题是你是否一次只想运行一个。 你为此付出了重大的性能损失。 一般情况下,您将使用第一个代码示例(其中唯一的显式依赖关系是完成操作),并将maxConcurrentOperationCount设置为4 ,从而享受并发性和随之而来的显着性能增益(同时,将并发度限制为一些合理的数字,不会用完所有的工作线程,冒险请求超时等)。

  3. 你还没有说这100个操作是什么,但是如果是一堆下载,你可能要考虑一个“延迟加载”模式,在你需要的时候asynchronous加载数据,而不是一次加载。

    例如,如果下载图像,可以使用AFNetworking UIImageView类别来实现。

这是一个常见问题的具体forms,即“如何调用一系列块操作并在最后一个完成时得到通知?”

一个想法是使用每个请求的参数来做一个“待办事项列表”。 说每个请求需要一个数字0..99。 现在伪代码看起来像这样:

 @property(nonatomic, copy) void (^done)(BOOL); // we'll need to save a completion block @property(nonatomic, strong) NSMutableArray *todo; // might as well save this too - (void)makeRequestsThenInvoke:(void (^)(BOOL))done { self.todo = [NSMutableArray arrayWithArray:@[@99, @98, @97 ... @0]]; // make this in a loop using real params to your network request (whatever distinguishes each request) self.done = done; [self makeRequests]; } - (void)makeRequests { if (!self.todo.count) { // nothing todo? then we're done self.done(YES); self.done = nil; // avoid caller-side retain cycle return; } // otherwise, get the next item todo NSNumber *param = [self.todo lastObject]; // build a url with param, eg http://myservice.com/request?param=%@ <- param goes there [afManager post:url success:success:^(AFHTTPRequestOperation *operation, id responseObject) { // handle the result // now update the todo list [self.todo removeLastObject]; // call ourself to do more, but use performSelector so we don't wind up the stack [self performSelector:@selector(makeRequests) withObject:nil afterDelay:0.0]; }]; }