Making non-self delegate in obj-c
In order to use asynchronous http requests in objective c, you need to set a delegate to NSURLConnection
. The problem is that I need to make multiple http requests, so开发者_如何学运维 having the same delegate (self) wont work.
What is the best way to go about this? Should I make a new delegate class for each http request? Are these delegates just NSObjects?
You have a few options. The two most most common are:
Make a new class for each connection (yes, a subclass of
NSObject
) and set them as delegates -- have them carry out whatever logic you need when the data is loadedSet one class as the delegate and store references to all of your
NSURLConnection
s. That way, when your delegate gets- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
called, you can test whichNSURLConnection
is being used (egif ([connection == myConnection])
-- or whichever delegate method you're implementing)
What I do is make a class that will handle downloading a file, and notify me when it is done through a selector. I pass it a delegate, a selector and the Info it needs to perform the download.
- (void) downloadFileFrom:(NSString*) httpLocation respondAt:(SEL)selector on:(id)target withParam:(id)param
{
self.finishSelector = selector;
self.delegate = target;
self.responseParams = param;
}
the Class is its own NSURLConnection delegate. Therefore the instance is separated from the others that I may instantiate, And it handles creating its own result for me to work with. I hold onto the param object. which could be anything.
At the end of the download it does a performSelector: on the delegate. passing itself to the delegate.
if ([self.target respondsToSelector:self.selector])
{
[self.target performSelector:self.selector withObject:self.param];
}
then you can create an instance of the downloader and call your method... telling it where to reply to you.
MyDownloader downloader = [[MyDownloader alloc] init];
[downloader downloadFileFrom:@"http://www.mydomain.com/myimage" respondAt:@selector(myFileIsComplete:) on:self withParam: downloader];
[downloader autorelease];
another option is to create a @protocol for your class to respond at, and have you delegate conform to the responder.
That should work, but there is another option to consider. You could make a generic class that creates and calls the NSURLConnection
provided they are common enough. Then keep an NSArray
or NSDictionary
of the classes. One for each connection.
Example: I have an app that needs to download several photos simultaneously. Therefore, I have a GetFlickrPhoto
class. It has a custom init method that receives the URL and any other necessary info. Each individual class creates the NSURLConnection
and can safely set the delegate to self
This helps keep things contained and very manageable/reusable.
To take it a step further:
The app I mentioned before, also needed to download JSON feeds. So I made a GenericDownload
class that took in URL and asynchronously downloaded the NSData
and then returned the NSData
to the calling delegate via defined success/failure protocols. It didn't care what the NSData
contained.
I remodeled GetFlickrPhoto
to call GenericDownload
and use the returned NSData
for a photo. I then made a GetJSON
class that also called GenericDownload
and parsed the returned NSData
into a JSON feed.
Takes a bit more time but in the end you will be glad for maintenance and future projects.
精彩评论