I'm using AFNetworking in my app, I'm checking for internet connectivity by their inbuilt class. Here's the code for this,

- (void) startInternetConnectivityMonitoring
{
    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status)
    {
        switch (status) {
            case AFNetworkReachabilityStatusUnknown:
            case AFNetworkReachabilityStatusReachableViaWWAN:
            case AFNetworkReachabilityStatusReachableViaWiFi:
                break;
            case AFNetworkReachabilityStatusNotReachable:
                break;
            default:
                break;
        }

        NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));

    }];

    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
}

and I can check for it by this function,

- (BOOL) connected {
    return [AFNetworkReachabilityManager sharedManager].reachable;
}

I'm also using RESideMenu in my app to have a side menu, this is my - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self startInternetConnectivityMonitoring];

    RootViewController *rootView = [[RootViewController alloc] init];
    [rootView awakeFromNib];
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = rootView;
    [self.window makeKeyAndVisible];
    return YES;
}

Everything is working fine for all other view controllers, except the FirstViewController. In FirstViewController I'm calling a networking request, before that, I do check for internet connectivity. Here's the problem. Each time, it show me No internet for FirstViewController. Because, while it call for a network request, AFNetworking don't update the status of internet. It may be a friction of seconds to update but its not updating that much fast. Since, I'm aware of the issue, I don't want to apply a patch to solve this. I tried different things to solve this. Used,

sleep(2); before return YES from didFinishLaunchingWithOptions...

dispatch_synq - Freeze the app

dispatch_asynq - Doesn't work

.. and many other hacky ways - Doesn't help yet.

5

There are 5 best solutions below

0
On BEST ANSWER

I found a simple patch for this, and yes it should work like a charm while I'll not find a reasonable solution for this problem.

  1. I took a BOOL in AppDelegate.h BOOL isCalledOnce;

  1. Added two methods like below in (AppDelegate.m)
- (void) setAppRequestCallOnce {
   isCalledOnce = YES;
}
 - (BOOL) checkAppRequestCalledOnce {
    return isCalledOnce;
 }

  1. In reachability check, I made a condition like this,
- (BOOL) connected {
    if(![self checkAppRequestCalledOnce]) {
        [self setAppRequestCallOnce];
        return YES;
    }
    return [AFNetworkReachabilityManager sharedManager].reachable;
}

Conclusion:

From FirstViewController when I check for the reachability, something like,

if(![delegateObj connected]) {
    //show no internet message
}

This will first call checkAppRequestCalledOnce method, which returns a isCalledOnce, if its NO then I'm set it to YES and return YES (here we're not sure for actual status of reachability). From now, when I again check for reachability then it'll not check for above condition and will return actual reachability status.

Why I'm using because, even if there'll be no internet available at start, AFNetworking will give us an error about it though we can show it even if we don't have actual status of reachability.

If you find any more elegant way then please post or comment.

0
On

I have also faced same kind of issue. After that I have tried to put some delay like 0.3 second in calling web-service and it solved my issue.

You may try to put some delay before calling web-service in FirstViewController. Because AFNetworking takes time to monitoring internet status and your controller loads before AFNetworking get internet status. So every time you will get AFNetworkReachabilityStatusNotReachable .

Put some delay before calling web-service in FirstViewController and it may solve your problem.

0
On

Unfortunately it takes a while to determine connectivity, so asap is probably not going to happen. But rather than to assume you have internet connection, you could also register to receive a Reachability notification. In AppDelegate didFinishLaunchingWithOptions:launchOptions start your monitoring:

[[AFNetworkReachabilityManager sharedManager] startMonitoring];

In your FirstViewController viewDidLoad or viewWillAppear, register to receive the notification:

 [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(reachabilityChanged:)
                                              name:AFNetworkingReachabilityDidChangeNotification
                                            object:nil];

Then add a method in FirstViewController to deal with the notification:

- (void)reachabilityChanged:(NSNotification *)notification
{       
    if([[AFNetworkReachabilityManager sharedManager].isReachable)
    {
        // Do web service stuff here
    }
    else
    {
        // Do non webservice stuff
    }

If you need to know what the status is, you can get that from the notification's userInfo dictionary:

- (void)reachabilityChanged:(NSNotification *)notification
{
    NSLog(@"Rechability Changed: %@", notification.userInfo);
    BOOL reachable;
    NSInteger status = [[notification.userInfo objectForKey:@"AFNetworkReachabilityNotificationStatusItem"] integerValue];
    switch(status)
    {
        case AFNetworkReachabilityStatusNotReachable:
            NSLog(@"No Internet Connection");
            reachable = NO;
            break;
        case AFNetworkReachabilityStatusReachableViaWiFi:
            NSLog(@"WIFI");
            reachable = YES;
            break;
        case AFNetworkReachabilityStatusReachableViaWWAN:
            NSLog(@"3G");
            reachable = YES;
            break;
        default:
            NSLog(@"Unkown network status");
            reachable = NO;
        break;
    }
    // do stuff with reachable
}

The notification is sent out as soon as the AFReachabilityManager has determined network status, and is always sent out at least once.

If you only need to get the status once, you can deregister FirstViewController from Notification Center in the method that deals with the notification - either from all notifications:

[[NSNotificationCenter defaultCenter] removeObserver:self];

or for the specific notification:

[[NSNotificationCenter defaultCenter] removeObserver:self name:AFNetworkingReachabilityDidChangeNotification object:nil];
0
On

I had a similar problem. It seems that AFNetworking needs a little time to kick in. If you want to check for internet connection in application:didFinishLaunchingWithOptions: use:

Reachability *reach = [Reachability reachabilityForInternetConnection];

if (reach.currentReachabilityStatus != NotReachable) {
    //NSLog(@"internet available");
}

or set the block on AFNetworking and wait until it gets called:

[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
    if (status < ReachableViaWiFi) {
        // no connection
    } else {
        // connected
    }
}];

[[AFNetworkReachabilityManager sharedManager] startMonitoring];
0
On

AFNetworking will tell you it hasn't determined the status yet if you check networkReachabilityStatus for AFNetworkReachabilityStatusUnknown. So the clean way to do this is only use the reachable status once it is known. For example:

- (void)networkReachableWithCompletion:(CompletionBlock)_completion
{
    if (!_completion) return; //no point continuing

    if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus != AFNetworkReachabilityStatusUnknown) {
        _completion([NSNumber numberWithBool:[AFNetworkReachabilityManager sharedManager].reachable]);
    } else {
        [self performSelector:@selector(networkReachableWithCompletion:) withObject:_completion afterDelay:0.3];
    }
}