Skip to content

Commit

Permalink
Merge pull request AFNetworking#197 from AFNetworking/experimental-ne…
Browse files Browse the repository at this point in the history
…twork-reachability-notification

Adding notifications for network reachability changes to AFHTTPClient
  • Loading branch information
mattt committed Feb 14, 2012
2 parents 09a5329 + 4266dc6 commit 06d1b3a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
13 changes: 12 additions & 1 deletion AFNetworking/AFHTTPClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,18 @@
@protocol AFMultipartFormData;

/**
Method used to encode parameters into request body
Posted when network reachability changes.
The notification object is an `NSNumber` object containing the boolean value for the current network reachability.
This notification contains no information in the `userInfo` dictionary.
@warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import <SystemConfiguration/SystemConfiguration.h>` to the header prefix of the project (Prefix.pch).
*/
#ifdef _SYSTEMCONFIGURATION_H
extern NSString * const AFNetworkingReachabilityDidChangeNotification;
#endif

/**
Method used to encode parameters into request body.
*/
typedef enum {
AFFormURLParameterEncoding,
Expand Down
50 changes: 35 additions & 15 deletions AFNetworking/AFHTTPClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#import <SystemConfiguration/SystemConfiguration.h>
#endif

NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";

static NSString * const kAFMultipartFormLineDelimiter = @"\r\n"; // CRLF
static NSString * const kAFMultipartFormBoundary = @"Boundary+0xAbCdEfGbOuNdArY";

Expand Down Expand Up @@ -148,6 +150,11 @@ @interface AFHTTPClient ()
@property (readwrite, nonatomic, retain) NSOperationQueue *operationQueue;
@property (readwrite, nonatomic, assign) AFNetworkReachabilityRef networkReachability;
@property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock;

#ifdef _SYSTEMCONFIGURATION_H
- (void)startMonitoringNetworkReachability;
- (void)stopMonitoringNetworkReachability;
#endif
@end

@implementation AFHTTPClient
Expand Down Expand Up @@ -193,21 +200,26 @@ - (id)initWithBaseURL:(NSURL *)url {
[self setDefaultHeader:@"User-Agent" value:[NSString stringWithFormat:@"%@/%@ (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey], @"unknown"]];
#endif

#ifdef _SYSTEMCONFIGURATION_H
[self startMonitoringNetworkReachability];
#endif

self.operationQueue = [[[NSOperationQueue alloc] init] autorelease];
[self.operationQueue setMaxConcurrentOperationCount:kAFHTTPClientDefaultMaxConcurrentOperationCount];

return self;
}

- (void)dealloc {
#ifdef _SYSTEMCONFIGURATION_H
[self stopMonitoringNetworkReachability];
#endif

[_baseURL release];
[_registeredHTTPOperationClassNames release];
[_defaultHeaders release];
[_operationQueue release];
[_networkReachabilityStatusBlock release];
if (_networkReachability) {
CFRelease(_networkReachability);
}

[super dealloc];
}
Expand All @@ -220,28 +232,36 @@ - (NSString *)description {

#ifdef _SYSTEMCONFIGURATION_H
static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
if (info) {
AFNetworkReachabilityStatusBlock block = (AFNetworkReachabilityStatusBlock)info;

BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
BOOL isNetworkReachable = (isReachable && !needsConnection);
BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
BOOL isNetworkReachable = (isReachable && !needsConnection);

AFNetworkReachabilityStatusBlock block = (AFNetworkReachabilityStatusBlock)info;
if (block) {
block(isNetworkReachable);
}

[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithBool:isNetworkReachable]];
}

- (void)setReachabilityStatusChangeBlock:(void (^)(BOOL isNetworkReachable))block {
- (void)startMonitoringNetworkReachability {
[self stopMonitoringNetworkReachability];
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);
}

- (void)stopMonitoringNetworkReachability {
if (_networkReachability) {
SCNetworkReachabilityUnscheduleFromRunLoop(_networkReachability, CFRunLoopGetMain(), (CFStringRef)NSRunLoopCommonModes);
CFRelease(_networkReachability);
}

}

- (void)setReachabilityStatusChangeBlock:(void (^)(BOOL isNetworkReachable))block {
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);
[self startMonitoringNetworkReachability];
}
#endif

Expand Down

0 comments on commit 06d1b3a

Please sign in to comment.