Search code examples
iosobjective-ciphonexcodensurlconnection

How many urlRequests are handled by nsurlconnection


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


Solution

  • 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.