完成每个请求后,按顺序执行NSURLConnection sendAsynchronousRequest的数量

时间:2015-03-12 09:36:47

标签: ios objective-c nsurlconnection

如何按顺序执行NSURLConnection sendAsynchronousRequest的数量?

我必须做各种异步请求并获得最终完成。

我想按特定顺序执行这些操作。 让我们说

sendAsynchronousRequest2应该在完成sendAsynchronousRequest1之后启动......依此类推......

ɲeuroburɳ在这个问题中的答案是有用的。但是,它并没有解决我的问题

Waiting until two async blocks are executed before starting another block

帮助将不胜感激

3 个答案:

答案 0 :(得分:2)

之前我做过类似的事情。我使用了一个自定义对象,该对象包含NSURLRequest实例和NSURLConnection样式completionHandler。创建了这些对象并将其添加到队列中 辅助方法使请求出列并发送。在NSURLConnection的原始completionHandler中,我调用了自定义对象的completionHandler,然后再次调用了helper方法。然后,这将使下一个请求出列。

在代码中看起来像这样:

@interface URLRequest: NSObject
@property (strong, nonatomic) NSURLRequest *request;
@property (copy, nonatomic) void (^completionHandler)(NSURLResponse *response, NSData *data, NSError *connectionError);
@end

@implementation URLRequest
@end

// viewController Interface
@property (strong) NSMutableArray *requestsQueue;

// implementation
- (BOOL)sendURLRequest {
    if ([self.requestsQueue count] > 0) {
        URLRequest *request = self.requestsQueue[0];
        [NSURLConnection sendAsynchronousRequest:request.request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
            NSLog(@"Request to url %@ done", response.URL);

            if (request.completionHandler) {
                request.completionHandler(response, data, connectionError);
            }
            [self.requestsQueue removeObjectAtIndex:0];

            if (![self sendURLRequest]) {
                NSLog(@"Queue Completed");
            }
        }];
        return YES;
    }
    else {
        NSLog(@"All requests send");
        return NO;
    }
}

- (void)addRequestToQueue:(URLRequest *)request {
    if (!self.requestsQueue) {
        self.requestsQueue = [NSMutableArray array];
    }
    BOOL queueWasEmpty = [self.requestsQueue count] == 0;
    [self.requestsQueue addObject:request];

    if (queueWasEmpty) {
        NSLog(@"Start request queue");
        [self sendURLRequest];
    }
}

URLRequest *request = [[URLRequest alloc] init];
request.request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]];
request.completionHandler = ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    NSLog(@"Request to www.google.com completed with status %ld", (long)((NSHTTPURLResponse *)response).statusCode);
};
[self addRequestToQueue:request];

request = [[URLRequest alloc] init];
request.request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.stackoverflow.com"]];
request.completionHandler = ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    NSLog(@"Request to www.stackoverflow.com completed with status %ld", (long)((NSHTTPURLResponse *)response).statusCode);
};
[self addRequestToQueue:request];

这是天真的版本。你必须考虑自己的错误(和超时)处理。

答案 1 :(得分:2)

你可以做类似以下的事情。

按照您希望完成的顺序将NSURLRequests添加到NSMutableArray。

然后调用'performRequestQueue'按顺序启动它们:

NSMutableArray *requests = ...

- (void)performRequestQueue {
    NSURLRequest *request = [requests firstObject];
    NSOperationQueue *rQueue = [[NSOperationQueue alloc] init];
    [NSURLConnection sendAsynchronousRequest:request queue:rQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        if ([data length] && error == nil) {
            // use data

            // remove current request from queue
            [requests removeObject:[requests firstObject]];
            if (requests.count > 0) {
                // if there are more, start next request
                [self performRequestQueue]
            } else {
                // else queue is complete, do whatever you need to here
                [self queueCompleted];
            }
        } else {
            // no data or error
        }
    }];
}

- (void)queueCompleted {
    // All NSURLConnections completed
}

答案 2 :(得分:1)

GCD信号量可以帮到你。

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
       // some operations 
       dispatch_semaphore_signal(semaphore);
    });

    // You will reach this point only after signal
    dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));

   // for more you just add one more async dispatch
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
       // some operations 
       dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));

在这种情况下,您将在块结束时以及何时需要更进一步时自行选择

您也可以使用NSOperationQueue(NSOperation Dependency)或GCD组

有关信号量的更多信息,请阅读此处 - https://developer.apple.com/library/prerelease/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html#//apple_ref/doc/uid/TP40008079-CH2-SW37