问题
I have to call 20 urlReqests at a time after going through many websites i have found that 4 urlRequsts are handled after that next undergoing requests will encounter error that is timeout error.when i call 5 webservices in a loop first 4 webservices are executing and 5th gets timeout error.How to handle this situation Any help would be appreciated
回答1:
You can use NSOperationQueue for such tasks. Here is the sample code-
Code for RequestManager.h :-
#import <Foundation/Foundation.h>
@protocol RequestManagerDelegate <NSObject>
@optional
- (void)requestForURL:(NSURL *)url tag:(NSString *)tag type:(NSString *)type
didComplete:(NSData *)data;
- (void)requestForURL:(NSURL *)url tag:(NSString *)tag type:(NSString *)type
didFailWithError:(NSError *)error;
@end
@interface RequestManager : NSObject
+ (RequestManager *) instance;
- (void)requestForURL:(NSURL *)url tag:(NSString *)tag delegate:(id<RequestManagerDelegate >)delegate;
@end
Code for RequestManager.m :-
#import "RequestManager.h"
@interface RequestManager () {
NSOperationQueue *requestQueue;
}
@end
@implementation RequestManager
static RequestManager *singletonInstance = nil;
- (id)init {
if(self = [super init]) {
requestQueue = [[NSOperationQueue alloc] init];
requestQueue.maxConcurrentOperationCount = 2;//Here you can select maximum concurrent operations
}
return self;
}
+ (RequestManager *) instance {
@synchronized(self) {
if(!singletonInstance) {
singletonInstance = [[RequestManager alloc] init];
}
}
return singletonInstance;
}
- (void)requestForURL:(NSURL *)url tag:(NSString *)tag delegate:(id<RequestManagerDelegate >)delegate {
[requestQueue setSuspended:YES];
RequestOperation *newOperation = [[RequestOperation alloc] initWithURL:url tag:tag delegate:delegate];
newOperation.queuePriority = NSOperationQueuePriorityVeryHigh;
[requestQueue addOperation:newOperation];
NSArray *operations = requestQueue.operations;
long operationsCount = operations.count;
RequestOperation *operation;
NSOperationQueuePriority priority = NSOperationQueuePriorityVeryHigh;
for(long i = (operationsCount - 1); i >= 0; i--) {
operation = [operations objectAtIndex:i];
if((operation.isExecuting || operation.isCancelled || operation.isFinished) == NO) {
[operation setQueuePriority:priority];
priority = [self nextPriorityLowerThan:priority];
}
}
[requestQueue setSuspended:NO];
}
- (NSOperationQueuePriority)nextPriorityLowerThan:(NSOperationQueuePriority)priority {
NSOperationQueuePriority lowerPriority = NSOperationQueuePriorityVeryLow;
switch (priority) {
case NSOperationQueuePriorityVeryHigh:
lowerPriority = NSOperationQueuePriorityHigh;
break;
case NSOperationQueuePriorityHigh:
lowerPriority = NSOperationQueuePriorityNormal;
break;
case NSOperationQueuePriorityNormal:
lowerPriority = NSOperationQueuePriorityLow;
break;
case NSOperationQueuePriorityLow:
lowerPriority = NSOperationQueuePriorityVeryLow;
break;
default:
break;
}
return lowerPriority;
}
@end
Now RequestOperation.h ->
#import <Foundation/Foundation.h>
@interface RequestOperation : NSOperation
@property(readonly, copy) NSURL *url;
@property(strong , readonly) NSString *tag;
@property(strong , readonly) id<RequestManagerDelegate > *delagate;
- (id)initWithURL:(NSURL *)url tag:(NSString *)tag delegate:(id<RequestManagerDelegate >) delegate;
@end
Now RequestOperation.m
#import "RequestOperation.h"
@interface RequestOperation ()
{
NSURLConnection *connection;
}
@property (nonatomic) long long int expectedContentLength;
@property (nonatomic, readwrite) NSError* error;
@property (nonatomic) BOOL isExecuting;
@property (nonatomic) BOOL isConcurrent;
@property (nonatomic) BOOL isFinished;
@end
@implementation RequestOperation
- (id)initWithURL:(NSURL *)url tag:(NSString *)tag delegate:(id<RequestManagerDelegate >) delegate{
if ((self=[super init])) {
_url = url;
_tag = tag;
_delagate=delagate;
}
return self;
}
- (void)start
{
NSURLRequest* request = [NSURLRequest requestWithURL:_url];
//handle here for your request type (post or get)
self.isExecuting = YES;
self.isConcurrent = YES;
self.isFinished = NO;
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
connection = [NSURLConnection connectionWithRequest:request delegate:self];
}];
}
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response {
return request;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
return cachedResponse;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
self.isExecuting = NO;
self.isFinished = YES;
}
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
self.error = error;
self.isExecuting = NO;
self.isFinished = YES;
}
- (void)setIsExecuting:(BOOL)isExecuting
{
[self willChangeValueForKey:@"isExecuting"];
_isExecuting = isExecuting;
[self didChangeValueForKey:@"isExecuting"];
}
- (void)setIsFinished:(BOOL)isFinished
{
[self willChangeValueForKey:@"isFinished"];
_isFinished = isFinished;
[self didChangeValueForKey:@"isFinished"];
}
- (void)cancel
{
[super cancel];
[connection cancel];
self.isFinished = YES;
self.isExecuting = NO;
}
@end
I given you the my code , this is how i managed multiple concurrent request asynchrounously. You can use this it is very effective. You can request the url using method declare in RequestManager.h and can handle the result using delegates.
来源:https://stackoverflow.com/questions/25503814/how-many-urlrequests-are-handled-by-nsurlconnection