5

I have written a tab based application in Xcode/RestKit and am attempting to use the RKReachabilityObserver to determine Internet connectivity on the device.

Ideally I'd like to have a single reachability variable throughout my application (if this is possible) but currently my implementation is as per the code below and does not work very well when replicated over my 4 tabs.

If anybody has any suggestions of a better way to do this, I'd really appreciate your comments.

View.h

@property (nonatomic, retain) RKReachabilityObserver *observer;

View.m

@interface AppViewController()
{
    RKReachabilityObserver *_observer;
}
@property (nonatomic) BOOL networkIsAvailable;
@synthesize observer = _observer;

-(id)initWithCoder:(NSCoder *)aDecoder {

    if ((self = [super initWithCoder:aDecoder])) {

        self.observer = [[RKReachabilityObserver alloc] initWithHost:@"mydomain"];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(reachabilityChanged:)
                                                     name:RKReachabilityDidChangeNotification
                                                   object:_observer];
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // determine network availability
    if (! [_observer isReachabilityDetermined]) {
        _networkIsAvailable = YES;
    }
    else
    {
        _networkIsAvailable = NO;
    }

    _text.returnKeyType = UIReturnKeyDone;
    _text.delegate = self;
}

- (void)reachabilityChanged:(NSNotification *)notification {
    RKReachabilityObserver* observer = (RKReachabilityObserver *) [notification object];
    if ([observer isNetworkReachable]) {
        if ([observer isConnectionRequired]) {
            _networkIsAvailable = YES;
            NSLog(@"Reachable");
            return;
        }
    } 
    else 
    {
        _networkIsAvailable = NO;
        NSLog(@"Not reachable");
    }
}

then anywhere in my view, I simply do....

if (_networkIsAvailable == YES)
    {...

I have implemented this over multiple views (which seems to be causing the problem.

What is the suggested approach for a multiple-view application?

Nick
  • 5,844
  • 11
  • 52
  • 98

2 Answers2

18

The [RKClient sharedClient] singleton already has a property for that (reachabilityObserver). Feel free to use that one.

if ([[[RKClient sharedClient] reachabilityObserver] isReachabilityDetermined] && [[RKClient sharedClient] isNetworkReachable]) {
    ....
}

You can also subscribe to RKReachabilityObserver notifications (if you want to take any action when reachability status changes)

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(reachabilityStatusChanged:) 
                                                 name:RKReachabilityDidChangeNotification object:nil];
mja
  • 5,056
  • 1
  • 29
  • 40
  • Hi mja. Is there a way to touch a selected host with the sharedClient singleton? Also, the time to first load is around 2 seconds. Is this normal? – Nick Jan 09 '12 at 09:04
  • There were some issues on iOS5 regarding the reachability API. It's best if you define your baseURL as IP address (if possible), then will RestKit use the IP to determine status - the issues were related to the way iOS handles DNS requests when determining the reachability status. Yes, there can be some delay. Are you testing on device or Simulator? If device, what iOS do you have (and also connectivity - Edge/3G/WiFi) – mja Jan 09 '12 at 10:24
  • Thanks mja. I'm on 3G & WiFi networks. The handset was connected via WiFi when the delay occured. I will try using the IP. – Nick Jan 09 '12 at 19:51
  • 1
    remember that in Restkit 0.2 RKClient is not available anymore – gdm Dec 09 '13 at 08:32
3

Here is some changes in RestKit 0.20 and later. The code of reachability block should looks like:

    RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[RemoteTools serverUrl]];
[manager.HTTPClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
    if (status == AFNetworkReachabilityStatusNotReachable) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No network connection"
                                                        message:@"You must be connected to the internet to use this app."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    }
}];
CTiPKA
  • 2,944
  • 1
  • 24
  • 27
  • is there a way to implement this once and do the same thing for all the screens? – jonypz Jan 15 '15 at 17:19
  • Just implement it for manager once and then use it as [RKObjectManager sharedManager]. So you alyaws use the same manager with implemented reachability block. – CTiPKA Jan 20 '15 at 10:52