Question

I am working on an RSS Reader which uses ASIHTTPRequest to download asynchronously the posts for each feed.

During the initial run, lots of connections happen at once and it appears to freeze the UI even though I use a 3-MOC solution (private for writing -> main for UI -> private for data edition).

I wonder how I could limit the ASIHTTPRequest class to limit its number of simultaneous connections to ... 2 or 4 instead of (I saw it in the debugger) dozens at once.

Was it helpful?

Solution

Using an ASINetworkQueue you create yourself gives you more control over asynchronous requests. When using a queue, only a certain number of requests can run at the same time. If you add more requests than the queue’s maxConcurrentOperationCount property, requests will wait for others to finish before they start.

An example showing how to manage a queue with ASIHTTPRequest:

#import <Foundation/Foundation.h>
#import <GHUnit/GHUnit.h>
@class ASINetworkQueue;

@interface MyController : NSObject {
    ASINetworkQueue *networkQueue;

}

- (void)doNetworkOperations;

@property (retain) ASINetworkQueue *networkQueue;

@end

-------------------------------------------------------------------

#import "MyController.h"
#import "ASIHTTPRequest.h"
#import "ASINetworkQueue.h"

@implementation MyController

- (void)dealloc
{
    [networkQueue release];
    [super dealloc];
}

- (void)doNetworkOperations
{
    // Stop anything already in the queue before removing it
    [[self networkQueue] cancelAllOperations];

    // Creating a new queue each time we use it means we don't have to worry about clearing delegates or resetting progress tracking
    [self setNetworkQueue:[ASINetworkQueue queue]];
    [[self networkQueue] setDelegate:self];
    [[self networkQueue] setRequestDidFinishSelector:@selector(requestFinished:)];
    [[self networkQueue] setRequestDidFailSelector:@selector(requestFailed:)];
    [[self networkQueue] setQueueDidFinishSelector:@selector(queueFinished:)];

    int i;
    for (i=0; i<5; i++) {
        ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
        [[self networkQueue] addOperation:request];
    }

    [[self networkQueue] go];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    // You could release the queue here if you wanted
    if ([[self networkQueue] requestsCount] == 0) {

        // Since this is a retained property, setting it to nil will release it
        // This is the safest way to handle releasing things - most of the time you only ever need to release in your accessors
        // And if you an Objective-C 2.0 property for the queue (as in this example) the accessor is generated automatically for you
        [self setNetworkQueue:nil]; 
    }

    //... Handle success
    NSLog(@"Request finished");
}

- (void)requestFailed:(ASIHTTPRequest *)request
{
    // You could release the queue here if you wanted
    if ([[self networkQueue] requestsCount] == 0) {
        [self setNetworkQueue:nil]; 
    }

    //... Handle failure
    NSLog(@"Request failed");
}


- (void)queueFinished:(ASINetworkQueue *)queue
{
    // You could release the queue here if you wanted
    if ([[self networkQueue] requestsCount] == 0) {
        [self setNetworkQueue:nil]; 
    }
    NSLog(@"Queue finished");
}

@synthesize networkQueue;
@end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top