Easiest way to detect Internet connection on iOS?

2019-01-01 09:35发布

I know this question will appear to be a dupe of many others, however, I don't feel the simple case is well explained here. Coming from an Android and BlackBerry background, making requests through HTTPUrlConnection instantly fail if there is no connection available. This seems like completely sane behavior, and I was surprised to find NSURLConnection in iOS did not emulate it.

I understand that Apple (and others who have extended it) provide a Reachability class to assist with determining the network state. I was happy to first see this and fully expected to see something like bool isNetworkAvailable(), but instead to my surprise I found a complex system requiring notification registrations and callbacks, and a bunch of seemingly unnecessary details. There must be a better way.

My app already gracefully handles connection failures, including no connectivity. The user is notified of the failure, and the app moves on.

Thus my requirements are simple: Single, synchronous function I can call before all HTTP requests to determine if I should bother actually sending the request or not. Ideally it requires no set up and just returns a boolean.

Is this really not possible on iOS?

16条回答
冷夜・残月
2楼-- · 2019-01-01 10:17

EDIT: This will not work for network URLs (see comments)

As of iOS 5, there is a new NSURL instance method:

- (BOOL)checkResourceIsReachableAndReturnError:(NSError **)error

Point it to the website you care about or point it to apple.com; I think it is the new one-line call to see if the internet is working on your device.

查看更多
明月照影归
3楼-- · 2019-01-01 10:18

You may also try this one if you already configured AFNetworking in your project.

-(void)viewDidLoad{  // -- add connectivity notification --//
[[NSNotificationCenter defaultCenter ] addObserver:self selector:@selector(ReachabilityDidChangeNotification:) name:AFNetworkingReachabilityDidChangeNotification object:nil];}
-(void)ReachabilityDidChangeNotification:(NSNotification *)notify
{
// -- NSLog(@"Reachability changed: %@", AFStringFromNetworkReachabilityStatus(status));  -- //
NSDictionary *userInfo =[notif userInfo];
AFNetworkReachabilityStatus status= [[userInfo valueForKey:AFNetworkingReachabilityNotificationStatusItem] intValue];
switch (status)
{
    case AFNetworkReachabilityStatusReachableViaWWAN:
    case AFNetworkReachabilityStatusReachableViaWiFi:
        // -- Reachable -- //
// -- Do your stuff when internet connection is available -- //
        [self getLatestStuff];
        NSLog(@"Reachable");
        break;
    case AFNetworkReachabilityStatusNotReachable:
    default:
        // -- Not reachable -- //
        // -- Do your stuff for internet connection not available -- //
NSLog(@"Not Reachable");
        break;
}
}
查看更多
永恒的永恒
4楼-- · 2019-01-01 10:20

Checking the Internet connection availability in (iOS) Xcode 8.2 , Swift 3.0

This is simple method for checking the network availability. I managed to translate it to Swift 2.0 and here the final code. The existing Apple Reachability class and other third party libraries seemed to be too complicated to translate to Swift.

This works for both 3G and WiFi connections.

Don’t forget to add “SystemConfiguration.framework” to your project builder.

//Create new swift class file Reachability in your project.

import SystemConfiguration

public class Reachability {
class func isConnectedToNetwork() -> Bool {
    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)
    let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
            SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
        }
    }
    var flags = SCNetworkReachabilityFlags()
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability! , &flags) {
        return false
    }
    let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
    let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
    return (isReachable && !needsConnection)
   }
}

// Check network connectivity from anywhere in project by using this code.

if Reachability.isConnectedToNetwork() == true {
     print("Internet connection OK")
} else {
 print("Internet connection FAILED")
}
查看更多
浪荡孟婆
5楼-- · 2019-01-01 10:24

I am writing the swift version of the accepted answer here, incase if someone finds it usefull, the code is written swift 2,

You can download the required files from SampleCode

Add Reachability.h and Reachability.m file to your project,

Now one will need to create Bridging-Header.h file if none exists for your project,

Inside your Bridging-Header.h file add this line :

#import "Reachability.h"

Now in order to check for Internet Connection

static func isInternetAvailable() -> Bool {
    let networkReachability : Reachability = Reachability.reachabilityForInternetConnection()
    let networkStatus : NetworkStatus = networkReachability.currentReachabilityStatus()

    if networkStatus == NotReachable {
        print("No Internet")
        return false
    } else {
        print("Internet Available")
        return true
    }

}
查看更多
残风、尘缘若梦
6楼-- · 2019-01-01 10:24

Alamofire

If you are already using Alamofire for all the RESTful Api, here is what you can benifit from that.

You can add following class to your app, and call MNNetworkUtils.main.isConnected() to get a boolean on whether its connected or not.

#import Alamofire

class MNNetworkUtils {
  static let main = MNNetworkUtils()
  init() {
    manager = NetworkReachabilityManager(host: "google.com")
    listenForReachability()
  }

  private let manager: NetworkReachabilityManager?
  private var reachable: Bool = false
  private func listenForReachability() {
    self.manager?.listener = { [unowned self] status in
      switch status {
      case .notReachable:
        self.reachable = false
      case .reachable(_), .unknown:
        self.reachable = true
      }
    }
    self.manager?.startListening()
  }

  func isConnected() -> Bool {
    return reachable
  }
}

This is a singleton class. Every time, when user connect or disconnect the network, it will override self.reachable to true/false correctly, because we start listening for the NetworkReachabilityManager on singleton initialization.

Also in order to monitor reachability, you need to provide a host, currently I am using google.com feel free to change to any other hosts or one of yours if needed.

查看更多
查无此人
7楼-- · 2019-01-01 10:26

I did a little more research and I am updating my answer with a more current solution. I am not sure if you have already looked at it but there is a nice sample code provided by Apple.

Download the sample code here

Include the Reachability.h and Reachability.m files in your project. Take a look at ReachabilityAppDelegate.m to see an example on how to determine host reachability, reachability by WiFi, by WWAN etc. For a very simply check of network reachability, you can do something like this

Reachability *networkReachability = [Reachability reachabilityForInternetConnection];   
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];    
if (networkStatus == NotReachable) {        
    NSLog(@"There IS NO internet connection");        
} else {        
     NSLog(@"There IS internet connection");        
}

@BenjaminPiette's: Don't forget to add SystemConfiguration.framework to your project.

查看更多
登录 后发表回答