From 95442be7b30bba2dce13e2fc38af5004dd1a4de2 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Tue, 10 Jan 2012 12:20:30 -0800 Subject: [PATCH] Initial implementation of network reachability callbacks --- AFNetworking/AFHTTPClient.h | 19 +++++++++++++++-- AFNetworking/AFHTTPClient.m | 42 +++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.h b/AFNetworking/AFHTTPClient.h index cb560f4..13c4782 100644 --- a/AFNetworking/AFHTTPClient.h +++ b/AFNetworking/AFHTTPClient.h @@ -35,6 +35,13 @@ typedef enum { AFPropertyListParameterEncoding, } AFHTTPClientParameterEncoding; +/** + */ +typedef enum { + AFNetworkNotReachable, + AFNetworkReachable, +} AFNetworkReachabilityStatus; + /** Returns a string, replacing certain characters with the equivalent percent escape sequence based on the specified encoding. @@ -157,9 +164,17 @@ extern NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *paramete */ - (id)initWithBaseURL:(NSURL *)url; -///---------------------------------- +///----------------------------------- +/// @name Managing Reachability Status +///----------------------------------- + +/** + */ +- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus reachabilityStatus))block; + +///------------------------------- /// @name Managing HTTP Operations -///---------------------------------- +///------------------------------- /** Attempts to register a subclass of `AFHTTPRequestOperation`, adding it to a chain to automatically generate request operations from a URL request. diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index a48ae00..768fa50 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -27,6 +27,7 @@ #import "AFJSONUtilities.h" #import +#import #if __IPHONE_OS_VERSION_MIN_REQUIRED #import @@ -49,6 +50,16 @@ static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY" #pragma mark - +typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus reachabilityStatus); + +static AFNetworkReachabilityStatus AFNetworkReachabilityStatusFromFlags(SCNetworkReachabilityFlags flags) { + if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) { + return AFNetworkNotReachable; + } else { + return AFNetworkReachable; + } +} + static NSUInteger const kAFHTTPClientDefaultMaxConcurrentOperationCount = 4; static NSString * AFBase64EncodedStringFromString(NSString *string) { @@ -124,6 +135,8 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) { @property (readwrite, nonatomic, retain) NSMutableArray *registeredHTTPOperationClassNames; @property (readwrite, nonatomic, retain) NSMutableDictionary *defaultHeaders; @property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue; +@property (readwrite, nonatomic, assign) SCNetworkReachabilityRef networkReachability; +@property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; @end @implementation AFHTTPClient @@ -133,6 +146,8 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) { @synthesize registeredHTTPOperationClassNames = _registeredHTTPOperationClassNames; @synthesize defaultHeaders = _defaultHeaders; @synthesize operationQueue = _operationQueue; +@synthesize networkReachability = _networkReachability; +@synthesize networkReachabilityStatusBlock = _networkReachabilityStatusBlock; + (AFHTTPClient *)clientWithBaseURL:(NSURL *)url { return [[[self alloc] initWithBaseURL:url] autorelease]; @@ -178,11 +193,38 @@ static NSString * AFPropertyListStringFromParameters(NSDictionary *parameters) { [_registeredHTTPOperationClassNames release]; [_defaultHeaders release]; [_operationQueue release]; + [_networkReachabilityStatusBlock release]; + if (_networkReachability) { + CFRelease(_networkReachability); + } + [super dealloc]; } #pragma mark - +static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { + if (info) { + AFNetworkReachabilityStatusBlock block = (AFNetworkReachabilityStatusBlock)info; + block(AFNetworkReachabilityStatusFromFlags(flags)); + } +} + +- (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus reachabilityStatus))block { + if (_networkReachability) { + SCNetworkReachabilityUnscheduleFromRunLoop(_networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes); + CFRelease(_networkReachability); + } + + self.networkReachabilityStatusBlock = block; + self.networkReachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [[self.baseURL host] UTF8String]); + SCNetworkReachabilityContext context = {0, self.networkReachabilityStatusBlock, NULL, NULL, NULL}; + SCNetworkReachabilitySetCallback(self.networkReachability, AFReachabilityCallback, &context); + SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes); +} + +#pragma mark - + - (BOOL)registerHTTPOperationClass:(Class)operationClass { if (![operationClass isSubclassOfClass:[AFHTTPRequestOperation class]]) { return NO;