views:

14289

answers:

7

I would like to check to see if I have an Internet connection on the iPhone using the Cocoa Touch libraries.

I came up with a way to do this using an NSUrl. The way I did it seems a bit unreliable (because even Google could one day be down and relying on a 3rd party seems bad) and while I could check to see for a response from some other websites if Google didn't respond, it does seem wasteful and an unnecessary overhead on my application.

- (BOOL) connectedToInternet
{
    NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];
    return ( URLString != NULL ) ? YES : NO;
}

Is what I have done bad? (Not to mention 'stringWithContentsOfURL' is deprecated in 3.0) And if so what is a better way to accomplish this?

Update (Unanswered):

It's been a long time, well the current answer is kind of outdated, so if you post the asynchronous code (using NSNotificationCenter) I will mark it as the new correct answer. I would answer it myself, but that seems that I would have a conflict of interest in marking my own answer as correct :)

A: 

The type of check that you propose would not accomplish anything since the connection could be lost immediately after the check or during the subsequent operation. Instead, you should put code that requires an internet connection in separate threads (I recommend using NSOperation and/or NSInvocationOperation for this task). If the data is not received within a certain period of time, inform the user that a connection could not be established.

titaniumdecoy
+3  A: 

Apple provides a sample app which does exactly this:

http://developer.apple.com/iphone/library/samplecode/Reachability/index.html

modeless
You should note that the Reachability sample only detects which interfaces are active, but not which ones have a valid connection to the internet. Applications should gracefully handle failure even when Reachability reports that everything is ready to go.
rpetrich
Happily the situation is a lot better in 3.0, as the system will present a login page for users behind a locked down WiFi where you have to login to use... you use to have to check for the redirect manually (and you still do if developing 2.2.1 apps)
Kendall Helmstetter Gelner
+10  A: 

Apple supply sample code to check for different types of network availability. Alternatively there is an example in the iPhone developers cookbook.

Note: Please see @KHG's comment on this answer regarding the use of Apple's reachability code.

teabot
Thanks. I discovered that the Xcode documentation in 3.0 also contains the source code, found by searching for "reachability" in the documentation.
Brock Woolf
Note that from experience, you should NOT use the Reachability code as-is. Note the part where the code mentions uncommenting a bit to use it asynchronosouly? Use that to get connectivity notifications.Also, always set the host value for reachability and do not use the reachability code as a pre-flight check to see if a connection is OK. Instead, start the Reachability notifications, then start you connection going - you'll get a notification right away if there i no connection and you can cancel the original request then issue an alert or do whatever you need to do.
Kendall Helmstetter Gelner
Note that the new revision (09-08-09) of the Reachability sample code from Apple is asynchronous.
Daniel Hepper
A: 

I've used the code in this discussion, and it seems to work fine (read the whole thread!).

I haven't tested it exhaustively with every conceivable kind of connection (like ad hoc wifi).

Felixyz
this code is not totally good because it just checks to see if you have wifi connection with a router, not if the web can be reached. You can have wifi working and continue enable to reach the web.
Digital Robot
+19  A: 

Edit: This used to be the correct answer, but is now outdated as you should subscribe to notifications for reachability instead. This methods checks synchronously:

You can use Apple's Reachability class. It will also allow you to check if WiFi is enabled:

Reachability* reachability = [Reachability sharedReachability];
[reachability setHostName:@"www.example.com"];    // set your host name here
NetworkStatus remoteHostStatus = [reachability remoteHostStatus];

if(remoteHostStatus == NotReachable) { }
else if (remoteHostStatus == ReachableViaWiFiNetwork) { }
else if (remoteHostStatus == ReachableViaCarrierDataNetwork) { }

The Reachability class is not shipped with the SDK, but rather a part of this Apple sample application. Just download it and copy Reachability.h/m to your project. Also, you have to add the SystemConfiguration framework to your project.

Daniel Rinser
See my comment above about not using Reachability like that. Use it in asynchronous mode and subscribe to the notifications it sends - don't.
Kendall Helmstetter Gelner
This code is a good starting point for things that you need to set before you can use the delegate methods for the reachability class.
Brock Woolf
here is a simple implementation of the Reachability class: http://duivesteyn.net/2010/03/16/iphone-os-sdk-checking-internet-reachability/
norskben
A: 

Nice topic, a bit old but thanks anyway it helped me. Only the Reachability class has been updated. You can now use:

Reachability* reachability = [Reachability reachabilityWithHostName:@"www.apple.com"];
NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];

if(remoteHostStatus == NotReachable) { NSLog(@"not reachable");}
else if (remoteHostStatus == ReachableViaWWAN) { NSLog(@"reachable via wwan");}
else if (remoteHostStatus == ReachableViaWiFi) { NSLog(@"reachable via wifi");}
Ben
Unless something changed since 4.0 was released, that code is not asynchronous and you are guaranteed to see it show up in Crash Reports - happened to me before.
bpapa
I agree with bpapa. It's not a good idea to use synchronous code. Thanks for the info though
Brock Woolf
+9  A: 

An updated answer:

1) Add SystemConfiguration framework to the project but don't worry about including it anywhere

2) Add Reachability.h and Reachability.m to the project

3) Add @class Reachability; to the .h file of where you are implementing the code

4) Create a couple instances to check in the interface section of the .h file:

    Reachability* internetReachable;
    Reachability* hostReachable;

5) Add a method in the .h for when the network status updates:

    - (void) checkNetworkStatus:(NSNotification *)notice;

6) Add #import "Reachability.h" to the .m file where you are implementing the check

7) In the .m file of where you are implementing the check, you can place this in one of the first methods called (init or viewWillAppear or viewDidLoad etc):

    -(void) viewWillAppear:(BOOL)animated
    {
        // check for internet connection
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];

        internetReachable = [[Reachability reachabilityForInternetConnection] retain];
        [internetReachable startNotifier];

        // check if a pathway to a random host exists
        hostReachable = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain];
        [hostReachable startNotifier];

        // now patiently wait for the notification
    }

8) Set up the method for when the notification gets sent and set whatever checks or call whatever methods you may have set up (in my case, I just set a BOOL)

    - (void) checkNetworkStatus:(NSNotification *)notice
    {
     // called after network status changes

     NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
     switch (internetStatus)

        {
      case NotReachable:
            {
       NSLog(@"The internet is down.");
       self.internetActive = NO;

                break;

            }
      case ReachableViaWiFi:
            {
       NSLog(@"The internet is working via WIFI.");
       self.internetActive = YES;

                break;

            }
      case ReachableViaWWAN:
            {
       NSLog(@"The internet is working via WWAN.");
       self.internetActive = YES;

                break;

            }
     }

     NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
     switch (hostStatus)

        {
      case NotReachable:
            {
       NSLog(@"A gateway to the host server is down.");
       self.hostActive = NO;

                break;

            }
      case ReachableViaWiFi:
            {
       NSLog(@"A gateway to the host server is working via WIFI.");
       self.hostActive = YES;

                break;

            }
      case ReachableViaWWAN:
            {
       NSLog(@"A gateway to the host server is working via WWAN.");
       self.hostActive = YES;

                break;

            }
     }
    }

9) In your dealloc or viewWillDisappear or similar method, remove yourself as an observer

    - (void) viewWillDisappear:(BOOL)animated
    {

            [[NSNotificationCenter defaultCenter] removeObserver:self];

    }

Note: There might be an instance using viewWillDisappear where you receive a memory warning and the observer never gets unregistered so you should account for that as well.

iWasRobbed
Nicely done thanks for the update answer
Brock Woolf
Perfect answer.
Lukasz
Step `2) Add Reachability.h and Reachability.m to the project` What do you mean by that? How shall we add it? create empty class or somehow else? Thanks
Burjua
Reachability.h and .m are included in Apple's Reachability example in the iPhone OS Reference Library. You get those files from there.
iWasRobbed
I feel this is a stupid question, but I'm going to ask it anyway. What exactly is the need for knowing if the internet is reachable, if we know whether or not the host is reachable? I mean obviously, if the host isn't and internet is, then possibly it's just the host that is problematic, but if I just want to know if I can reach my host, I shouldn't need to care about the internet reachability should I?
littleknown
When they talk about the host being reachable, they are actually talking about whether or not a *gateway* to the host is reachable or not. They don't mean to say that "google.com" or "apple.com" is available, but moreso that a means of getting there is available.
iWasRobbed