Thursday, November 5, 2009

NSURLConnection subclass

So I wanted a way to handle multiple NSURLConnections for different functional areas. The problem with the normal NSURLConnection is the inability to distinguish between the different connections unless you look at the URL.

Which is fine, but just looking at the URL doesn't help when I have multiple objects that use similar URLs and need to keep them separated. One common solution you find on the internet is to subclass NSURLConnection and add a tag variable. Which is what I did, but I needed more than just that.

I also didn't want to have to keep track of multiple sets of data from the different connections so I created a variable for the data and overloaded the methods that send delegate responses to handle the data.

Now it's getting closer to what I wanted. The last thing I wanted was there was only one instance of a connection for each tag. So I created a class variable to handle that.

So in the end, what I had was an NSURLConnection subclass that handles multiple tagged connections with the response data contained in the connection and limiting the connections to 1 instance of each tag.


Anyways, here's the subclass definition:

#import

NSMutableDictionary *instances;

@interface tagConnection : NSURLConnection {

NSString *connID;

NSMutableData *receivedData;

}

@property (retain) NSString *connID;

@property (retain) NSMutableData *receivedData;

+ (void)checkTag:(NSString *)tag Target:(tagConnection *)target;

+ (void)removeTag:(NSString *)tag;

- (id)initWithTag:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately connID:(NSString*)tag;

@end


And this is the class implementation:

#import "tagConnection.h"


@implementation tagConnection

@synthesize connID;

@synthesize receivedData;


+ (void)initialize {

instances = [[NSMutableDictionary alloc] init];

}


+ (void)checkTag:(NSString *)tag Target:(tagConnection *)target{

tagConnection *tempConn = [instances objectForKey:tag];

if (tempConn != nil) {

[tempConn cancel];

[tempConn release];

}

[instances setObject:target forKey:tag];

}


+ (void)removeTag:(NSString *)tag {

[instances removeObjectForKey:tag];

}


- (id)initWithTag:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately connID:(NSString*)tag {

self = [super initWithRequest:request delegate:delegate startImmediately:(BOOL)startImmediately];

if (self) {

self.connID = tag;

receivedData = [[NSMutableData alloc] initWithLength:0];

[tagConnection checkTag:connID Target:self];

}

return self;

}


- (void)dealloc {

[tagConnection removeTag:connID];

[receivedData release];

[connID release];

[super dealloc];

}


- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveResponse:(NSURLResponse *)response cacheStoragePolicy:(NSURLCacheStoragePolicy)policy {

[receivedData setLength:0];

}


- (void)URLProtocol:(NSURLProtocol *)protocol didLoadData:(NSData *)data {

[receivedData appendData:data];

}

@end


And here is some sample code of how to implement the subclass:

- (void)applicationDidFinishLaunching:(UIApplication *)application {

NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://wwww.yahoo.com"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15];

[theRequest setValue:@"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4" forHTTPHeaderField:@"user-agent"];

tagConnection *testConn1 = [[tagConnection alloc] initWithTag:theRequest delegate:self startImmediately:YES connID:@"test"];

tagConnection *testConn2 = [[tagConnection alloc] initWithTag:theRequest delegate:self startImmediately:YES connID:@"test"];

}


- (void)connection:(tagConnection *)connection didFailWithError:(NSError *)error {

[connection release];

}


- (void)connectionDidFinishLoading:(tagConnection *)connection {

[connection receivedData]; //Do something with the data;

[connection release];

}

2 comments:

  1. all I can say Is huh? but WOW didn't expect such a quick turn around Looks like it really challenges you as well as draws your interest I'd like to and I will ask more about what this mumbo jumbo ( what is to me now) means so I can understand what it doing..... well how this process is allowing you to enable the functions your trying to create and I know if I look at the podcast I would but I need the sort version I'll read it 6 more times before I do

    ReplyDelete
  2. Well, it's going to be hard to understand if you have no programming experience or no objective programming experience. I just needed a way to track the multiple internet connections I was making to a website. I didn't test it a whole lot but after I tried to use it in my program, I realized I made a mistake in the code so I will have to amend it at some point.

    ReplyDelete