Reputation: 2421
As a lot of people do, I want to perform NSURLConnections
asynchronously but in series such that each requests's response doesn't step over / append onto the other's.
I have a HTTP request helper that doesn't the following:
@property (nonatomic,retain) NSURLConnection *connection;
@property (nonatomic,retain) NSOperationQueue *queue;
@property (nonatomic,retain) NSURLResponse *response;
@property (nonatomic,retain) NSMutableData *responseData;
@end
@implementation HttpRequester
@synthesize delegate = _delegate;
- (id)init {
if(self = [super init]) {
_connection = nil;
// create our queue
_queue = [[NSOperationQueue alloc] init];
_queue.maxConcurrentOperationCount = 1; // one request at a time
_response = nil;
_responseData = nil;
}
return self;
}
- (void)sendRequest:(NSURLRequest *)request {
_connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:NO];
[_connection setDelegateQueue:_queue];
[_connection start];
}
Is it enough to create that NSOperationQueue
w/ max count 1 and set that against my NSURLConnection
such that each call to sendRequest
will queue the NSURLConnectionDelegate
callbacks until the previous one has finished?
If not, I suppose the most straight forward approach would be to implement a queue around these requests I just want to understand the behavior here more.
Thanks.
Upvotes: 0
Views: 581
Reputation: 50109
Since a network request is asynchronous (and you didn't use the sendSynchronousRequest helper), the operation is finishes right after starting the request and the queue moves on. If you want the queue to 'wait' for the async portion of an operation, you need to implement:
- (BOOL)isConcurrent {
return YES;
}
then the operation queue uses KVO to monitor an operation's isFinished method.
so do:
@implementation MyOp {
BOOL _isFinished;
}
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isReady {
return YES;
}
- (BOOL)isFinished {
return _isFinished;
}
...
THEN do what you do above and in didReceiveResponse. when you are 100% done, do
[self willChangeValueForKey:@"isFinished"];
_isFinished = YES;
[self didChangeValueForKey:@"isFinished"];
Upvotes: 1
Reputation: 2421
I'm also trying a simplified approach here:
@property (nonatomic,strong) NSOperationQueue *requestQueue;
@end
@implementation HttpRequester
- (id)init {
if(self = [super init]) {
_requestQueue = [[NSOperationQueue alloc] init];
_requestQueue.maxConcurrentOperationCount = 1; // one request at a time
}
return self;
}
- (void)sendRequest:(NSURLRequest *)request {
[NSURLConnection sendAsynchronousRequest:request queue:_requestQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if (error != nil) {
// error occurred
// do something
}
else if (data != nil && data.length > 0) {
// success
// do something
}
}];
}
But I'm not sure if there are any advantages of one approach to another.
Upvotes: 0