Last active
August 29, 2015 14:13
-
-
Save alexruperez/51f504da05ddb307450a to your computer and use it in GitHub Desktop.
Revisions
-
alexruperez revised this gist
Jan 14, 2015 . 2 changed files with 73 additions and 14 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,7 +8,7 @@ #import <Foundation/Foundation.h> @interface ARURLOperation : NSOperation <NSURLConnectionDataDelegate, NSSecureCoding, NSCopying> @property (nonatomic, strong, readonly) NSURLRequest *request; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,15 +8,17 @@ #import "ARURLOperation.h" @interface ARURLOperation () { BOOL _executing; BOOL _finished; } @property (nonatomic, strong, readwrite) NSURLConnection *connection; @property (nonatomic, strong, readwrite) NSMutableData *responseMutableData; @property (nonatomic, strong, readwrite) NSRecursiveLock *lock; @end @@ -26,10 +28,10 @@ - (void)networkRequestThreadEntryPoint:(id)__unused object { @autoreleasepool { [NSThread currentThread].name = [NSString stringWithFormat:@"%@Thread", NSStringFromClass(self.class)]; NSRunLoop *runLoop = NSRunLoop.currentRunLoop; [runLoop addPort:NSMachPort.port forMode:NSDefaultRunLoopMode]; [runLoop run]; } } @@ -58,6 +60,8 @@ - (instancetype)init - (instancetype)initWithRequest:(NSURLRequest *)request { NSParameterAssert(request); self = [super init]; if (self) @@ -66,6 +70,8 @@ - (instancetype)initWithRequest:(NSURLRequest *)request _finished = NO; _request = request; self.lock = NSRecursiveLock.new; self.lock.name = [NSString stringWithFormat:@"%@Lock", NSStringFromClass(self.class)]; self.name = NSStringFromClass(self.class); } @@ -74,10 +80,10 @@ - (instancetype)initWithRequest:(NSURLRequest *)request - (NSData *)responseData { return [NSData dataWithBytes:self.responseMutableData.bytes length:self.responseMutableData.length]; } - (BOOL)isAsynchronous { return YES; } @@ -92,8 +98,18 @@ - (BOOL)isFinished return _finished; } - (NSString *)description { [self.lock lock]; NSString *description = [NSString stringWithFormat:@"<%@: %p, cancelled: %@ request: %@, response: %@>", NSStringFromClass(self.class), self, (self.isCancelled ? @"YES" : @"NO"), self.request, self.response]; [self.lock unlock]; return description; } - (void)start { [self.lock lock]; if (self.isCancelled) { [self willChangeValueForKey:@"isFinished"]; @@ -108,23 +124,32 @@ - (void)start { [self willChangeValueForKey:@"isExecuting"]; [self performSelector:@selector(main) onThread:self.networkRequestThread withObject:nil waitUntilDone:NO modes:@[NSRunLoopCommonModes]]; _executing = YES; [self didChangeValueForKey:@"isExecuting"]; } [self.lock unlock]; } - (void)main { [self.lock lock]; if (!self.isCancelled && [NSURLConnection canHandleRequest:self.request]) { self.responseMutableData = NSMutableData.new; self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO]; [self.connection scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes]; [self.connection start]; } [self.lock unlock]; } - (void)completeOperation @@ -139,6 +164,8 @@ - (void)completeOperation [self didChangeValueForKey:@"isFinished"]; } # pragma mark - NSURLConnectionDataDelegate - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { if (!self.isCancelled) @@ -163,14 +190,46 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespon - (void)connectionDidFinishLoading:(NSURLConnection *)connection { self.connection = nil; [self completeOperation]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { _error = error; self.connection = nil; [self completeOperation]; } #pragma mark - NSSecureCoding + (BOOL)supportsSecureCoding { return YES; } - (id)initWithCoder:(NSCoder *)decoder { NSURLRequest *request = [decoder decodeObjectOfClass:NSURLRequest.class forKey:NSStringFromSelector(@selector(request))]; self = [self initWithRequest:request]; return self; } - (void)encodeWithCoder:(NSCoder *)coder { [coder encodeObject:self.request forKey:NSStringFromSelector(@selector(request))]; } #pragma mark - NSCopying - (id)copyWithZone:(NSZone *)zone { return [(ARURLOperation *)[self.class allocWithZone:zone] initWithRequest:self.request];; } @end -
alexruperez created this gist
Jan 13, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,25 @@ // // ARURLOperation.h // ARURLOperation // // Created by alexruperez on 13/1/15. // // #import <Foundation/Foundation.h> @interface ARURLOperation : NSOperation @property (nonatomic, strong, readonly) NSURLRequest *request; @property (nonatomic, strong, readonly) NSURLResponse *response; @property (nonatomic, strong, readonly) NSData *responseData; @property (nonatomic, strong, readonly) NSError *error; + (instancetype)operationWithRequest:(NSURLRequest *)request; - (instancetype)initWithRequest:(NSURLRequest *)request NS_DESIGNATED_INITIALIZER; @end This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,176 @@ // // ARURLOperation.m // ARURLOperation // // Created by alexruperez on 13/1/15. // // #import "ARURLOperation.h" @interface ARURLOperation () <NSURLConnectionDataDelegate> { BOOL _executing; BOOL _finished; } @property (nonatomic, strong) NSURLConnection *connection; @property (nonatomic, strong) NSMutableData *responseMutableData; @end @implementation ARURLOperation - (void)networkRequestThreadEntryPoint:(id)__unused object { @autoreleasepool { [[NSThread currentThread] setName:[NSString stringWithFormat:@"%@Thread", NSStringFromClass(self.class)]]; NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; [runLoop run]; } } - (NSThread *)networkRequestThread { static NSThread *_networkRequestThread = nil; static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate, ^{ _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil]; [_networkRequestThread start]; }); return _networkRequestThread; } + (instancetype)operationWithRequest:(NSURLRequest *)request { return [[self alloc] initWithRequest:request]; } - (instancetype)init { return [self initWithRequest:nil]; } - (instancetype)initWithRequest:(NSURLRequest *)request { self = [super init]; if (self) { _executing = NO; _finished = NO; _request = request; self.name = NSStringFromClass(self.class); } return self; } - (NSData *)responseData { return [self.responseMutableData copy]; } - (BOOL)isConcurrent { return YES; } - (BOOL)isExecuting { return _executing; } - (BOOL)isFinished { return _finished; } - (void)start { if (self.isCancelled) { [self willChangeValueForKey:@"isFinished"]; _finished = YES; [self didChangeValueForKey:@"isFinished"]; return; } else if (self.isReady) { [self willChangeValueForKey:@"isExecuting"]; [self performSelector:@selector(main) onThread:[self networkRequestThread] withObject:nil waitUntilDone:NO modes:@[NSRunLoopCommonModes]]; _executing = YES; [self didChangeValueForKey:@"isExecuting"]; } } - (void)main { self.responseMutableData = [[NSMutableData alloc] init]; self.connection = [[NSURLConnection alloc] initWithRequest:_request delegate:self startImmediately:NO]; [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [self.connection start]; } - (void)completeOperation { [self willChangeValueForKey:@"isFinished"]; [self willChangeValueForKey:@"isExecuting"]; _executing = NO; _finished = YES; [self didChangeValueForKey:@"isExecuting"]; [self didChangeValueForKey:@"isFinished"]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { if (!self.isCancelled) { [self.responseMutableData appendData:data]; return; } [self completeOperation]; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { if (!self.isCancelled) { _response = response; return; } [self completeOperation]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [self completeOperation]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { _error = error; [self completeOperation]; } @end