Cocoa-NetworkChange
view release on metacpan or search on metacpan
src/Reachability.m view on Meta::CPAN
#pragma mark - notifier methods
// Notifier
// NOTE: this uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD
// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS.
// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want)
-(BOOL)startNotifier
{
SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL };
// this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves
// woah
self.reachabilityObject = self;
// first we need to create a serial queue
// we allocate this once for the lifetime of the notifier
self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL);
if(!self.reachabilitySerialQueue)
{
return NO;
}
#if __has_feature(objc_arc)
context.info = (__bridge void *)self;
#else
context.info = (void *)self;
#endif
if (!SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context))
{
#ifdef DEBUG
NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError()));
#endif
//clear out the dispatch queue
if(self.reachabilitySerialQueue)
{
#if NEEDS_DISPATCH_RETAIN_RELEASE
dispatch_release(self.reachabilitySerialQueue);
#endif
self.reachabilitySerialQueue = nil;
}
self.reachabilityObject = nil;
return NO;
}
// set it as our reachability queue which will retain the queue
if(!SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue))
{
#ifdef DEBUG
NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError()));
#endif
//UH OH - FAILURE!
// first stop any callbacks!
SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
// then clear out the dispatch queue
if(self.reachabilitySerialQueue)
{
#if NEEDS_DISPATCH_RETAIN_RELEASE
dispatch_release(self.reachabilitySerialQueue);
#endif
self.reachabilitySerialQueue = nil;
}
self.reachabilityObject = nil;
return NO;
}
return YES;
}
-(void)stopNotifier
{
// first stop any callbacks!
SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
// unregister target from the GCD serial dispatch queue
SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL);
if(self.reachabilitySerialQueue)
{
#if NEEDS_DISPATCH_RETAIN_RELEASE
dispatch_release(self.reachabilitySerialQueue);
#endif
self.reachabilitySerialQueue = nil;
}
self.reachabilityObject = nil;
}
#pragma mark - reachability tests
// this is for the case where you flick the airplane mode
// you end up getting something like this:
//Reachability: WR ct-----
//Reachability: -- -------
//Reachability: WR ct-----
//Reachability: -- -------
// we treat this as 4 UNREACHABLE triggers - really apple should do better than this
#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection)
-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags
{
BOOL connectionUP = YES;
if(!(flags & kSCNetworkReachabilityFlagsReachable))
connectionUP = NO;
if( (flags & testcase) == testcase )
connectionUP = NO;
#if TARGET_OS_IPHONE
if(flags & kSCNetworkReachabilityFlagsIsWWAN)
{
// we're on 3G
if(!self.reachableOnWWAN)
{
// we dont want to connect when on 3G
connectionUP = NO;
}
}
#endif
return connectionUP;
}
-(BOOL)isReachable
{
SCNetworkReachabilityFlags flags;
if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
return NO;
( run in 2.013 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )