Skip to content

Instantly share code, notes, and snippets.

@maxhuk
Created April 9, 2013 13:04
Show Gist options
  • Save maxhuk/5345539 to your computer and use it in GitHub Desktop.
Save maxhuk/5345539 to your computer and use it in GitHub Desktop.
Cancelable NSURLConnection with exact timeout.
//
// AsyncURLConnection.h
//
// Created by Maksym Huk on 10/31/12.
// Copyright (c) 2012 Maksym Huk. All rights reserved.
//
#import <Foundation/Foundation.h>
// Send request with exact timeout
@interface AsyncURLConnection : NSObject
+ (AsyncURLConnection *)connectionWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler;
- (void)connectionWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler;
- (void)cancel;
@end
//
// AsyncURLConnection.m
//
// Created by Maksym Huk on 10/31/12.
// Copyright (c) 2012 Maksym Huk. All rights reserved.
//
#import "AsyncURLConnection.h"
@interface AsyncURLConnection () <NSURLConnectionDataDelegate>
@end
@implementation AsyncURLConnection
{
NSURLConnection *_connection;
NSTimer *_timer;
void (^_handler)(NSURLResponse*, NSData*, NSError*);
NSURLResponse *_response;
NSMutableData *_data;
}
- (void)connectionWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
{
_handler = handler;
_response = nil;
_data = [NSMutableData data];
dispatch_async(dispatch_get_main_queue(), ^{
_timer = [NSTimer timerWithTimeInterval:request.timeoutInterval
target:self
selector:@selector(requestDidTimeout:)
userInfo:nil
repeats:NO];
_connection = [NSURLConnection connectionWithRequest:request delegate:self];
});
}
- (void)cancel
{
[_connection cancel];
}
+ (AsyncURLConnection *)connectionWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
{
AsyncURLConnection *connection = [[AsyncURLConnection alloc] init];
[connection connectionWithRequest:request completionHandler:handler];
return connection;
}
- (void)requestDidTimeout:(NSTimer *)timer
{
NSURL *url = _connection.currentRequest.URL;
[_connection cancel];
_connection = nil;
_timer = nil;
_handler(_response, _data, [NSError errorWithDomain:NSPOSIXErrorDomain code:ETIMEDOUT userInfo:@{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Connection timed out to URL: %@", url] }]);
}
#pragma mark - NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[_timer invalidate];
_timer = nil;
_handler(_response, _data, error);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
_response = response;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_data appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[_timer invalidate];
_timer = nil;
_handler(_response, _data, nil);
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment