Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

4.0 Compatibility changes

  • Loading branch information...
commit 73683cb214c8e457b464e01d0e8631313dd4f283 1 parent 54c0b54
@deepwinter authored
View
18 Rhus.xcodeproj/project.pbxproj
@@ -96,6 +96,8 @@
F4AA3F4D14DA5B3E00ED3CCE /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4AA3F4C14DA5B3E00ED3CCE /* Security.framework */; };
F4AA3F4F14DA5B4A00ED3CCE /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F4AA3F4E14DA5B4A00ED3CCE /* libz.dylib */; };
F4AA3F5314DA5BBA00ED3CCE /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F4AA3F5214DA5BBA00ED3CCE /* libstdc++.dylib */; };
+ F4C1734F154B698100A929E1 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = F4C1734E154B698100A929E1 /* Reachability.m */; };
+ F4C17352154B74FF00A929E1 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4C17351154B74FF00A929E1 /* SystemConfiguration.framework */; };
F4CE8858150C08A3009AE0FC /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4CE8857150C08A3009AE0FC /* CoreLocation.framework */; };
F4D3929414BBA6660051E831 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D3929314BBA6660051E831 /* UIKit.framework */; };
F4D3929614BBA6660051E831 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D3929514BBA6660051E831 /* Foundation.framework */; };
@@ -234,6 +236,9 @@
F4AA3F4E14DA5B4A00ED3CCE /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
F4AA3F5214DA5BBA00ED3CCE /* libstdc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.dylib"; path = "usr/lib/libstdc++.dylib"; sourceTree = SDKROOT; };
F4C0624514BE6D0A0008FBB5 /* GHUnitIOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GHUnitIOS.framework; path = "../../IphoneDevelopment/Libs/gh-unit/Project-iOS/build/Framework/GHUnitIOS.framework"; sourceTree = "<group>"; };
+ F4C1734D154B698100A929E1 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; };
+ F4C1734E154B698100A929E1 /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = "<group>"; };
+ F4C17351154B74FF00A929E1 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; };
F4CE8857150C08A3009AE0FC /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
F4D3928F14BBA6660051E831 /* Rhus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Rhus.app; sourceTree = BUILT_PRODUCTS_DIR; };
F4D3929314BBA6660051E831 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
@@ -251,6 +256,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ F4C17352154B74FF00A929E1 /* SystemConfiguration.framework in Frameworks */,
F4CE8858150C08A3009AE0FC /* CoreLocation.framework in Frameworks */,
F4AA3F5314DA5BBA00ED3CCE /* libstdc++.dylib in Frameworks */,
F4AA3F4F14DA5B4A00ED3CCE /* libz.dylib in Frameworks */,
@@ -336,6 +342,7 @@
F414D9AF1549F325008A38F5 /* Source */ = {
isa = PBXGroup;
children = (
+ F4C1734C154B698100A929E1 /* Third Party */,
F414D9B01549F325008A38F5 /* Categories */,
F414D9B71549F325008A38F5 /* DataModels */,
F414D9C01549F325008A38F5 /* Maps */,
@@ -448,6 +455,15 @@
path = Settings;
sourceTree = "<group>";
};
+ F4C1734C154B698100A929E1 /* Third Party */ = {
+ isa = PBXGroup;
+ children = (
+ F4C1734D154B698100A929E1 /* Reachability.h */,
+ F4C1734E154B698100A929E1 /* Reachability.m */,
+ );
+ path = "Third Party";
+ sourceTree = "<group>";
+ };
F4CE8B30150C10AA009AE0FC /* Targets */ = {
isa = PBXGroup;
children = (
@@ -473,6 +489,7 @@
F4D3928414BBA6650051E831 = {
isa = PBXGroup;
children = (
+ F4C17351154B74FF00A929E1 /* SystemConfiguration.framework */,
F414DA3B1549F3D2008A38F5 /* Settings */,
F4CE8B30150C10AA009AE0FC /* Targets */,
A6A620D814BBBB670096CA01 /* Graphics */,
@@ -698,6 +715,7 @@
F414DA311549F325008A38F5 /* SwoopTabViewController.m in Sources */,
F414DA371549F325008A38F5 /* TimelineVisualizationView.m in Sources */,
F4F942A4154B25B00091279C /* RHSettings_Rhus.m in Sources */,
+ F4C1734F154B698100A929E1 /* Reachability.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
3  Source/DataModels/RHDataModel.h
@@ -19,10 +19,13 @@ typedef void ( ^CompletedBlock )();
CouchPersistentReplication* _pull;
CouchPersistentReplication* _push;
CompletedBlock syncCompletedBlock;
+ BOOL syncStarted;
+ NSTimer * syncTimeoutTimer;
}
@property (nonatomic, strong) CouchDatabase *database;
@property (nonatomic, strong) CouchLiveQuery* query;
+@property (nonatomic, strong) NSTimer * syncTimeoutTimer;
- (id) initWithBlock: ( void ( ^ )() ) didStartBlock ;
View
55 Source/DataModels/RHDataModel.m
@@ -24,6 +24,7 @@ + (id)instance
@synthesize database;
@synthesize query;
+@synthesize syncTimeoutTimer;
- (id) initWithBlock:( void ( ^ )() ) didStartBlock {
@@ -363,15 +364,39 @@ - (void)showAlert: (NSString*)message error: (NSError*)error fatal: (BOOL)fatal
}
+-(void)syncTimeout {
+ if(!syncStarted){
+ NSLog(@"Sync Timeout");
+
+ UIAlertView* alert = [[UIAlertView alloc] initWithTitle: @"No Sync"
+ message: @"Timed out while trying to sync, either there is nothing to sync or you aren't connected to the internet. Make sure you are connected to the internet and try again!"
+ delegate: nil
+ cancelButtonTitle: @"OK"
+ otherButtonTitles: nil];
+ [alert show];
+ [self forgetSync];
+ if(syncCompletedBlock){
+ syncCompletedBlock();
+ }
+ syncCompletedBlock = nil;
+ }
+}
+
- (void)updateSyncURL {
[self updateSyncURLWithCompletedBlock: nil];
}
+
- (void)updateSyncURLWithCompletedBlock: ( CompletedBlock ) setCompletedBlock {
+ //Should check for reachability of data.winterroot.net
+ //http://stackoverflow.com/questions/1083701/how-to-check-for-an-active-internet-connection-on-iphone-sdk
- NSInteger count = [self.database getDocumentCount];
+
+ //Test for network
+ NSInteger count = [self.database getDocumentCount];
+
if (!self.database){
NSLog(@"No Database in updateSyncURL");
return;
@@ -387,26 +412,40 @@ - (void)updateSyncURLWithCompletedBlock: ( CompletedBlock ) setCompletedBlock {
NSArray* repls = [self.database replicateWithURL: newRemoteURL exclusively: YES];
_pull = [repls objectAtIndex: 0];
_push = [repls objectAtIndex: 1];
- // _pull.filter = @"design/excludeDesignDocs";
- // _push.filter = @"rhusMobile/excludeDesignDocs";
+ //_pull.continuous = NO; //we might want these not to be continuous for user initialized replications
+ //_push.continuous = NO;
+ // _pull.filter = @"design/excludeDesignDocs";
+ // _push.filter = @"rhusMobile/excludeDesignDocs";
[_pull addObserver: self forKeyPath: @"completed" options: 0 context: NULL];
[_push addObserver: self forKeyPath: @"completed" options: 0 context: NULL];
- [_pull addObserver: self forKeyPath: @"state" options: 0 context: NULL];
- [_push addObserver: self forKeyPath: @"state" options: 0 context: NULL];
+
+
syncCompletedBlock = setCompletedBlock;
+ //set a timeout to detect when there are in fact no changes
+ //This is only relevant when sync is NOT continuous
+
+ /*NSInvocation * invocation = [[NSInvocation alloc] init];
+ [invocation setTarget:self];
+ [invocation setSelector:@selector(syncTimeout)];
+ syncStarted = FALSE;
+ self.syncTimeoutTimer = [NSTimer timerWithTimeInterval:5.0 invocation:invocation repeats:NO];
+ */
+ syncStarted = FALSE;
+ self.syncTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(syncTimeout) userInfo:nil repeats:NO];
+
+
}
+
- (void) forgetSync {
[_pull removeObserver: self forKeyPath: @"completed"];
- [_pull removeObserver: self forKeyPath: @"state"];
_pull = nil;
[_push removeObserver: self forKeyPath: @"completed"];
- [_push removeObserver: self forKeyPath: @"state"];
_push = nil;
}
@@ -414,6 +453,8 @@ - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if (object == _pull || object == _push) {
+ syncStarted = TRUE;
+
unsigned completed = _pull.completed + _push.completed;
unsigned total = _pull.total + _push.total;
NSLog(@"SYNC progress: %u / %u", completed, total);
View
93 Source/Third Party/Reachability.h
@@ -0,0 +1,93 @@
+/*
+ Copyright (c) 2011, Tony Million.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+#import <SystemConfiguration/SystemConfiguration.h>
+
+#import <sys/socket.h>
+#import <netinet/in.h>
+#import <netinet6/in6.h>
+#import <arpa/inet.h>
+#import <ifaddrs.h>
+#import <netdb.h>
+
+extern NSString *const kReachabilityChangedNotification;
+
+typedef enum
+{
+ // Apple NetworkStatus Compatible Names.
+ NotReachable = 0,
+ ReachableViaWiFi = 2,
+ ReachableViaWWAN = 1
+} NetworkStatus;
+
+@class Reachability;
+
+typedef void (^NetworkReachable)(Reachability * reachability);
+typedef void (^NetworkUnreachable)(Reachability * reachability);
+
+@interface Reachability : NSObject
+
+@property (nonatomic, copy) NetworkReachable reachableBlock;
+@property (nonatomic, copy) NetworkUnreachable unreachableBlock;
+
+@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef;
+@property (nonatomic, assign) dispatch_queue_t reachabilitySerialQueue;
+
+@property (nonatomic, assign) BOOL reachableOnWWAN;
+
+@property (nonatomic, strong) id reachabilityObject;
+
++(Reachability*)reachabilityWithHostname:(NSString*)hostname;
++(Reachability*)reachabilityForInternetConnection;
++(Reachability*)reachabilityWithAddress:(const struct sockaddr_in*)hostAddress;
++(Reachability*)reachabilityForLocalWiFi;
+
+-(Reachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref;
+
+-(BOOL)startNotifier;
+-(void)stopNotifier;
+
+-(BOOL)isReachable;
+-(BOOL)isReachableViaWWAN;
+-(BOOL)isReachableViaWiFi;
+
+// WWAN may be available, but not active until a connection has been established.
+// WiFi may require a connection for VPN on Demand.
+-(BOOL)isConnectionRequired; // Identical DDG variant.
+-(BOOL)connectionRequired; // Apple's routine.
+// Dynamic, on demand connection?
+-(BOOL)isConnectionOnDemand;
+// Is user intervention required?
+-(BOOL)isInterventionRequired;
+
+-(NetworkStatus)currentReachabilityStatus;
+-(SCNetworkReachabilityFlags)reachabilityFlags;
+-(NSString*)currentReachabilityString;
+-(NSString*)currentReachabilityFlags;
+
+@end
View
465 Source/Third Party/Reachability.m
@@ -0,0 +1,465 @@
+/*
+ Copyright (c) 2011, Tony Million.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "Reachability.h"
+
+
+NSString *const kReachabilityChangedNotification = @"kReachabilityChangedNotification";
+
+@interface Reachability (private)
+
+-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags;
+-(BOOL)setReachabilityTarget:(NSString*)hostname;
+
+-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags;
+
+@end
+
+static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags)
+{
+ return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c",
+#if TARGET_OS_IPHONE
+ (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
+#else
+ 'X',
+#endif
+ (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
+ (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
+ (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
+ (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
+ (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
+ (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
+ (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
+ (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-'];
+}
+
+//Start listening for reachability notifications on the current run loop
+static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
+{
+#pragma unused (target)
+ Reachability *reachability = ((__bridge Reachability*)info);
+
+ // we probably dont need an autoreleasepool here as GCD docs state each queue has its own autorelease pool
+ // but what the heck eh?
+ @autoreleasepool
+ {
+ [reachability reachabilityChanged:flags];
+ }
+}
+
+
+@implementation Reachability
+
+@synthesize reachabilityRef;
+@synthesize reachabilitySerialQueue;
+
+@synthesize reachableOnWWAN;
+
+@synthesize reachableBlock;
+@synthesize unreachableBlock;
+
+@synthesize reachabilityObject;
+
+#pragma mark - class constructor methods
++(Reachability*)reachabilityWithHostname:(NSString*)hostname
+{
+ SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]);
+ if (ref)
+ {
+ id reachability = [[self alloc] initWithReachabilityRef:ref];
+
+#if __has_feature(objc_arc)
+ return reachability;
+#else
+ return [reachability autorelease];
+#endif
+
+ }
+
+ return nil;
+}
+
++(Reachability *)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress
+{
+ SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
+ if (ref)
+ {
+ id reachability = [[self alloc] initWithReachabilityRef:ref];
+
+#if __has_feature(objc_arc)
+ return reachability;
+#else
+ return [reachability autorelease];
+#endif
+ }
+
+ return nil;
+}
+
++(Reachability *)reachabilityForInternetConnection
+{
+ struct sockaddr_in zeroAddress;
+ bzero(&zeroAddress, sizeof(zeroAddress));
+ zeroAddress.sin_len = sizeof(zeroAddress);
+ zeroAddress.sin_family = AF_INET;
+
+ return [self reachabilityWithAddress:&zeroAddress];
+}
+
++(Reachability*)reachabilityForLocalWiFi
+{
+ struct sockaddr_in localWifiAddress;
+ bzero(&localWifiAddress, sizeof(localWifiAddress));
+ localWifiAddress.sin_len = sizeof(localWifiAddress);
+ localWifiAddress.sin_family = AF_INET;
+ // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
+ localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
+
+ return [self reachabilityWithAddress:&localWifiAddress];
+}
+
+
+// initialization methods
+
+-(Reachability *)initWithReachabilityRef:(SCNetworkReachabilityRef)ref
+{
+ self = [super init];
+ if (self != nil)
+ {
+ self.reachableOnWWAN = YES;
+ self.reachabilityRef = ref;
+ }
+
+ return self;
+}
+
+-(void)dealloc
+{
+ [self stopNotifier];
+ if(self.reachabilityRef)
+ {
+ CFRelease(self.reachabilityRef);
+ self.reachabilityRef = nil;
+ }
+#ifdef DEBUG
+ NSLog(@"Reachability: dealloc");
+#endif
+
+#if !(__has_feature(objc_arc))
+ [super dealloc];
+#endif
+
+
+}
+
+#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;
+
+ context.info = (__bridge void *)self;
+
+ if (!SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context))
+ {
+#ifdef DEBUG
+ NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError()));
+#endif
+ return NO;
+ }
+
+ //create a serial queue
+ self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL);
+
+ // set it as our reachability queue which will retain the queue
+ if(SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue))
+ {
+ dispatch_release(self.reachabilitySerialQueue);
+ // refcount should be ++ from the above function so this -- will mean its still 1
+ return YES;
+ }
+
+ dispatch_release(self.reachabilitySerialQueue);
+ self.reachabilitySerialQueue = nil;
+ return NO;
+}
+
+-(void)stopNotifier
+{
+ // first stop any callbacks!
+ SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
+
+ // unregister target from the GCD serial dispatch queue
+ // this will mean the dispatch queue gets dealloc'ed
+ if(self.reachabilitySerialQueue)
+ {
+ SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL);
+ 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;
+
+ return [self isReachableWithFlags:flags];
+}
+
+-(BOOL)isReachableViaWWAN
+{
+#if TARGET_OS_IPHONE
+
+ SCNetworkReachabilityFlags flags = 0;
+
+ if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
+ {
+ // check we're REACHABLE
+ if(flags & kSCNetworkReachabilityFlagsReachable)
+ {
+ // now, check we're on WWAN
+ if(flags & kSCNetworkReachabilityFlagsIsWWAN)
+ {
+ return YES;
+ }
+ }
+ }
+#endif
+
+ return NO;
+}
+
+-(BOOL)isReachableViaWiFi
+{
+ SCNetworkReachabilityFlags flags = 0;
+
+ if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
+ {
+ // check we're reachable
+ if((flags & kSCNetworkReachabilityFlagsReachable))
+ {
+#if TARGET_OS_IPHONE
+ // check we're NOT on WWAN
+ if((flags & kSCNetworkReachabilityFlagsIsWWAN))
+ {
+ return NO;
+ }
+#endif
+ return YES;
+ }
+ }
+
+ return NO;
+}
+
+
+// WWAN may be available, but not active until a connection has been established.
+// WiFi may require a connection for VPN on Demand.
+-(BOOL)isConnectionRequired
+{
+ return [self connectionRequired];
+}
+
+-(BOOL)connectionRequired
+{
+ SCNetworkReachabilityFlags flags;
+
+ if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
+ {
+ return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
+ }
+
+ return NO;
+}
+
+// Dynamic, on demand connection?
+-(BOOL)isConnectionOnDemand
+{
+ SCNetworkReachabilityFlags flags;
+
+ if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
+ {
+ return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
+ (flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand)));
+ }
+
+ return NO;
+}
+
+// Is user intervention required?
+-(BOOL)isInterventionRequired
+{
+ SCNetworkReachabilityFlags flags;
+
+ if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
+ {
+ return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
+ (flags & kSCNetworkReachabilityFlagsInterventionRequired));
+ }
+
+ return NO;
+}
+
+
+#pragma mark - reachability status stuff
+
+-(NetworkStatus)currentReachabilityStatus
+{
+ if([self isReachable])
+ {
+ if([self isReachableViaWiFi])
+ return ReachableViaWiFi;
+
+#if TARGET_OS_IPHONE
+ return ReachableViaWWAN;
+#endif
+ }
+
+ return NotReachable;
+}
+
+-(SCNetworkReachabilityFlags)reachabilityFlags
+{
+ SCNetworkReachabilityFlags flags = 0;
+
+ if(SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
+ {
+ return flags;
+ }
+
+ return 0;
+}
+
+-(NSString*)currentReachabilityString
+{
+ NetworkStatus temp = [self currentReachabilityStatus];
+
+ if(temp == reachableOnWWAN)
+ {
+ // updated for the fact we have CDMA phones now!
+ return NSLocalizedString(@"Cellular", @"");
+ }
+ if (temp == ReachableViaWiFi)
+ {
+ return NSLocalizedString(@"WiFi", @"");
+ }
+
+ return NSLocalizedString(@"No Connection", @"");
+}
+
+-(NSString*)currentReachabilityFlags
+{
+ return reachabilityFlags([self reachabilityFlags]);
+}
+
+#pragma mark - callback function calls this method
+
+-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags
+{
+#ifdef DEBUG
+ NSLog(@"Reachability: %@", reachabilityFlags(flags));
+#endif
+
+ if([self isReachableWithFlags:flags])
+ {
+ if(self.reachableBlock)
+ {
+#ifdef DEBUG
+ NSLog(@"Reachability: blocks are not called on the main thread.\n Use dispatch_async(dispatch_get_main_queue(), ^{}); to update your UI!");
+#endif
+ self.reachableBlock(self);
+ }
+ }
+ else
+ {
+ if(self.unreachableBlock)
+ {
+#ifdef DEBUG
+ NSLog(@"Reachability: blocks are not called on the main thread.\n Use dispatch_async(dispatch_get_main_queue(), ^{}); to update your UI!");
+#endif
+ self.unreachableBlock(self);
+ }
+ }
+
+ // this makes sure the change notification happens on the MAIN THREAD
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification
+ object:self];
+ });
+}
+
+@end
View
8 Source/Views and Controllers/AppDelegate.h
@@ -9,23 +9,29 @@
#import <UIKit/UIKit.h>
#import "SwoopTabViewController.h"
#import "LoadingViewController.h"
+#import "Reachability.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
SwoopTabViewController * swoopTabViewController;
BOOL isDoneStartingUp;
+ BOOL internetActive;
+ Reachability * internetReachable;
}
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) SwoopTabViewController * swoopTabViewController;
@property (strong, nonatomic) LoadingViewController * loadingViewController;
-//@property (nonatomic) BOOL isDoneStartingUp;
+@property (strong, nonatomic) Reachability * internetReachable;
+@property (nonatomic) BOOL internetActive;
- (void) initializeAppDelegateAndLaunch;
- (void) initializeDataModel;
- (void) initializeInBackground;
- (void) doneStartingUp;
+- (void) checkNetworkStatus:(NSNotification *)notice;
+
@end
View
43 Source/Views and Controllers/AppDelegate.m
@@ -18,6 +18,8 @@ @implementation AppDelegate
@synthesize window = _window;
@synthesize swoopTabViewController;
@synthesize loadingViewController;
+@synthesize internetActive;
+@synthesize internetReachable;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
@@ -68,6 +70,14 @@ - (void) initializeAppDelegateAndLaunch {
[RHDataModel instance];
+
+ // check for internet connection
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
+
+ self.internetActive = YES;
+ self.internetReachable = [Reachability reachabilityForInternetConnection];
+ [internetReachable startNotifier];
+
[self performSelectorInBackground:@selector(initializeInBackground) withObject:nil];
// [self initializeInBackground];
@@ -190,4 +200,35 @@ - (void)applicationWillTerminate:(UIApplication *)application
*/
}
-@end
+
+-(void) checkNetworkStatus:(NSNotification *)notice
+{
+ // called after network status changes
+ NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
+ switch (internetStatus)
+ {
+ case NotReachable:
+ {
+ NSLog(@"The internet is down.");
+ internetActive = NO;
+
+ break;
+ }
+ case ReachableViaWiFi:
+ {
+ NSLog(@"The internet is working via WIFI.");
+ internetActive = YES;
+
+ break;
+ }
+ case ReachableViaWWAN:
+ {
+ NSLog(@"The internet is working via WWAN.");
+ internetActive = YES;
+
+ break;
+ }
+ }
+}
+
+@end
View
13 Source/Views and Controllers/MapViewController.m
@@ -15,6 +15,7 @@
#import "RHDocument.h"
#import "RHSettings.h"
#import "RHDeviceUser.h"
+#import "AppDelegate.h"
//Map Settings
#define mapInsetOriginX 10
@@ -697,6 +698,18 @@ - (IBAction)didTapOverlay:(id)sender{
}
- (IBAction)didTabSync:(id)sender{
+ if( ! [ (AppDelegate *) [[UIApplication sharedApplication] delegate] internetActive] ) {
+ UIAlertView * alert = [[UIAlertView alloc] initWithTitle: @"Internet Not Available"
+ message: @"The internet is not currently available. Please wait until you are able to connect to the interet in order to sync"
+ delegate: nil
+ cancelButtonTitle: @"OK"
+ otherButtonTitles: nil];
+ [alert show];
+ return;
+
+ }
+
+
[self.view addSubview:self.spinnerContainerView];
UIActivityIndicatorView *ai = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.spinnerContainerView addSubview:ai];
Please sign in to comment.
Something went wrong with that request. Please try again.