-
-
Save zoul/578636 to your computer and use it in GitHub Desktop.
@interface DownloadOperation : NSOperation | |
{ | |
NSURLRequest *request; | |
NSURLConnection *connection; | |
NSMutableData *receivedData; | |
} | |
@property(readonly) BOOL isExecuting; | |
@property(readonly) BOOL isFinished; | |
@property(readonly) NSData *receivedData; | |
- (id) initWithRequest: (NSURLRequest*) rq; | |
@end |
#import "DownloadOperation.h" | |
@interface DownloadOperation () | |
@property(assign) BOOL isExecuting; | |
@property(assign) BOOL isFinished; | |
@end | |
@implementation DownloadOperation | |
@synthesize isExecuting, isFinished, receivedData; | |
#pragma mark Initialization | |
- (id) initWithRequest: (NSURLRequest*) rq | |
{ | |
[super init]; | |
request = [rq retain]; | |
return self; | |
} | |
- (void) dealloc | |
{ | |
[request release]; | |
[super dealloc]; | |
} | |
#pragma mark NSOperation Stuff | |
- (void) start | |
{ | |
NSParameterAssert(request); | |
// Bail out early if cancelled. | |
if ([self isCancelled]) { | |
[self setIsFinished:YES]; | |
[self setIsExecuting:NO]; | |
return; | |
} | |
[self setIsExecuting:YES]; | |
[self setIsFinished:NO]; | |
receivedData = [[NSMutableData alloc] init]; | |
// Make sure the connection runs in the main run loop. | |
connection = [[NSURLConnection alloc] initWithRequest:request | |
delegate:self startImmediately:NO]; | |
[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] | |
forMode:NSDefaultRunLoopMode]; | |
[connection start]; | |
} | |
- (BOOL) isConcurrent | |
{ | |
return YES; | |
} | |
#pragma mark NSURLConnection Callbacks | |
- (void) connection: (NSURLConnection*) cn didReceiveData: (NSData*) data | |
{ | |
// Not cancelled, receive data. | |
if (![self isCancelled]) { | |
[receivedData appendData:data]; | |
return; | |
} | |
// Cancelled, tear down connection. | |
[self setIsExecuting:NO]; | |
[self setIsFinished:YES]; | |
[connection cancel]; | |
[connection release]; | |
[receivedData release]; | |
} | |
- (void) connectionDidFinishLoading: (NSURLConnection*) cn | |
{ | |
[self setIsExecuting:NO]; | |
[self setIsFinished:YES]; | |
[receivedData release]; | |
[connection release]; | |
} | |
- (void) connection: (NSURLConnection*) cn didFailWithError: (NSError*) error | |
{ | |
[self setIsExecuting:NO]; | |
[self setIsFinished:YES]; | |
[connection release]; | |
[receivedData release]; | |
} | |
// http://stackoverflow.com/questions/3573236 | |
+ (BOOL) automaticallyNotifiesObserversForKey: (NSString*) key | |
{ | |
return YES; | |
} | |
@end |
You’re right, thanks. That was a leftover from the original code.
Hm. I'm not sure you really need to release the delegate. According to the NSURLConnection documentation:
Special Considerations
The connection retains delegate. It releases delegate when the connection finishes loading, fails, or is canceled.
Dear zoul,
Thanks for sharing this.
Is there any advantage to run NSURLConnection within a concurrent NSOperation? I suppose it is possible to have the same effect just creating a wrapper around the connection.
My supposition is that I could use queues in order to manage the number of running operations, dependencies among operations and so on.
I ask it since the connection is shunted on the main thread and, so, callbacks will be called on that thread. So, no threading mechanism is involved here.
Thank you for your attention.
One minor issue I'd like to note:
@property(readonly) BOOL downloadOK;
This code is not used and throws a compiler warning.