iPhone Sdk Internet Connection Detection

How can I check for an active Internet connection on iOS or macOS?

Important: This check should always be performed asynchronously. The majority of answers below are synchronous so be careful otherwise you'll freeze up your app.



Swift

  1. Install via CocoaPods or Carthage: https://github.com/ashleymills/Reachability.swift

  2. Test reachability via closures

    let reachability = Reachability()!

    reachability.whenReachable = { reachability in
    if reachability.connection == .wifi {
    print("Reachable via WiFi")
    } else {
    print("Reachable via Cellular")
    }
    }

    reachability.whenUnreachable = { _ in
    print("Not reachable")
    }

    do {
    try reachability.startNotifier()
    } catch {
    print("Unable to start notifier")
    }


Objective-C

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

  2. Add Tony Million's version of Reachability.h and Reachability.m to the project (found here: https://github.com/tonymillion/Reachability)

  3. Update the interface section

    #import "Reachability.h"

    // Add this to the interface in the .m file of your view controller
    @interface MyViewController ()
    {
    Reachability *internetReachableFoo;
    }
    @end
  4. Then implement this method in the .m file of your view controller which you can call

    // Checks if we have an internet connection or not
    - (void)testInternetConnection
    {
    internetReachableFoo = [Reachability reachabilityWithHostname:@"www.google.com"];

    // Internet is reachable
    internetReachableFoo.reachableBlock = ^(Reachability*reach)
    {
    // Update the UI on the main thread
    dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"Yayyy, we have the interwebs!");
    });
    };

    // Internet is not reachable
    internetReachableFoo.unreachableBlock = ^(Reachability*reach)
    {
    // Update the UI on the main thread
    dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"Someone broke the internet :(");
    });
    };

    [internetReachableFoo startNotifier];
    }

Important Note: The Reachability class is one of the most used classes in projects so you might run into naming conflicts with other projects. If this happens, you'll have to rename one of the pairs of Reachability.h and Reachability.m files to something else to resolve the issue.

Note: The domain you use doesn't matter. It's just testing for a gateway to any domain.

iPhone SDK Internet connection detection

If your application must have network access the easiest way is to add the following settings to your info.plist as boolean values.

  • SBUsesNetwork - Ensure the device has an active connection (Edit: not applicable, this seems to be a private API someone found at some point. It is not in Apple's developer documentation.)
  • UIRequiresPersistentWiFi - Ensures the device is connected via WiFi

If your choice is not true then the user will be presented with an appropriate message when starting your application. Best of all this message is from the OS and thus is localized.

If your application cannot download data from a website while running (loss of signal, site down) you should still warn the user though and not just spin indefinitely.

Check for internet connection with Swift

To solve the 4G issue mentioned in the comments I have used @AshleyMills reachability implementation as a reference and rewritten Reachability for Swift 3.1:

updated: Xcode 10.1 • Swift 4 or later


Reachability.swift file

import Foundation
import SystemConfiguration

class Reachability {
var hostname: String?
var isRunning = false
var isReachableOnWWAN: Bool
var reachability: SCNetworkReachability?
var reachabilityFlags = SCNetworkReachabilityFlags()
let reachabilitySerialQueue = DispatchQueue(label: "ReachabilityQueue")
init(hostname: String) throws {
guard let reachability = SCNetworkReachabilityCreateWithName(nil, hostname) else {
throw Network.Error.failedToCreateWith(hostname)
}
self.reachability = reachability
self.hostname = hostname
isReachableOnWWAN = true
try start()
}
init() throws {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let reachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
throw Network.Error.failedToInitializeWith(zeroAddress)
}
self.reachability = reachability
isReachableOnWWAN = true
try start()
}
var status: Network.Status {
return !isConnectedToNetwork ? .unreachable :
isReachableViaWiFi ? .wifi :
isRunningOnDevice ? .wwan : .unreachable
}
var isRunningOnDevice: Bool = {
#if targetEnvironment(simulator)
return false
#else
return true
#endif
}()
deinit { stop() }
}

extension Reachability {

func start() throws {
guard let reachability = reachability, !isRunning else { return }
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
context.info = Unmanaged<Reachability>.passUnretained(self).toOpaque()
guard SCNetworkReachabilitySetCallback(reachability, callout, &context) else { stop()
throw Network.Error.failedToSetCallout
}
guard SCNetworkReachabilitySetDispatchQueue(reachability, reachabilitySerialQueue) else { stop()
throw Network.Error.failedToSetDispatchQueue
}
reachabilitySerialQueue.async { self.flagsChanged() }
isRunning = true
}

func stop() {
defer { isRunning = false }
guard let reachability = reachability else { return }
SCNetworkReachabilitySetCallback(reachability, nil, nil)
SCNetworkReachabilitySetDispatchQueue(reachability, nil)
self.reachability = nil
}

var isConnectedToNetwork: Bool {
return isReachable &&
!isConnectionRequiredAndTransientConnection &&
!(isRunningOnDevice && isWWAN && !isReachableOnWWAN)
}

var isReachableViaWiFi: Bool {
return isReachable && isRunningOnDevice && !isWWAN
}

/// Flags that indicate the reachability of a network node name or address, including whether a connection is required, and whether some user intervention might be required when establishing a connection.
var flags: SCNetworkReachabilityFlags? {
guard let reachability = reachability else { return nil }
var flags = SCNetworkReachabilityFlags()
return withUnsafeMutablePointer(to: &flags) {
SCNetworkReachabilityGetFlags(reachability, UnsafeMutablePointer($0))
} ? flags : nil
}

/// compares the current flags with the previous flags and if changed posts a flagsChanged notification
func flagsChanged() {
guard let flags = flags, flags != reachabilityFlags else { return }
reachabilityFlags = flags
NotificationCenter.default.post(name: .flagsChanged, object: self)
}

/// The specified node name or address can be reached via a transient connection, such as PPP.
var transientConnection: Bool { return flags?.contains(.transientConnection) == true }

/// The specified node name or address can be reached using the current network configuration.
var isReachable: Bool { return flags?.contains(.reachable) == true }

/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set, the kSCNetworkReachabilityFlagsConnectionOnTraffic flag, kSCNetworkReachabilityFlagsConnectionOnDemand flag, or kSCNetworkReachabilityFlagsIsWWAN flag is also typically set to indicate the type of connection required. If the user must manually make the connection, the kSCNetworkReachabilityFlagsInterventionRequired flag is also set.
var connectionRequired: Bool { return flags?.contains(.connectionRequired) == true }

/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. Any traffic directed to the specified name or address will initiate the connection.
var connectionOnTraffic: Bool { return flags?.contains(.connectionOnTraffic) == true }

/// The specified node name or address can be reached using the current network configuration, but a connection must first be established.
var interventionRequired: Bool { return flags?.contains(.interventionRequired) == true }

/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. The connection will be established "On Demand" by the CFSocketStream programming interface (see CFStream Socket Additions for information on this). Other functions will not establish the connection.
var connectionOnDemand: Bool { return flags?.contains(.connectionOnDemand) == true }

/// The specified node name or address is one that is associated with a network interface on the current system.
var isLocalAddress: Bool { return flags?.contains(.isLocalAddress) == true }

/// Network traffic to the specified node name or address will not go through a gateway, but is routed directly to one of the interfaces in the system.
var isDirect: Bool { return flags?.contains(.isDirect) == true }

/// The specified node name or address can be reached via a cellular connection, such as EDGE or GPRS.
var isWWAN: Bool { return flags?.contains(.isWWAN) == true }

/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set
/// The specified node name or address can be reached via a transient connection, such as PPP.
var isConnectionRequiredAndTransientConnection: Bool {
return (flags?.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]) == true
}
}

func callout(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
guard let info = info else { return }
DispatchQueue.main.async {
Unmanaged<Reachability>
.fromOpaque(info)
.takeUnretainedValue()
.flagsChanged()
}
}

extension Notification.Name {
static let flagsChanged = Notification.Name("FlagsChanged")
}

struct Network {
static var reachability: Reachability!
enum Status: String {
case unreachable, wifi, wwan
}
enum Error: Swift.Error {
case failedToSetCallout
case failedToSetDispatchQueue
case failedToCreateWith(String)
case failedToInitializeWith(sockaddr_in)
}
}

Usage

Initialize it in your AppDelegate.swift didFinishLaunchingWithOptions method and handle any errors that might occur:

import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
do {
try Network.reachability = Reachability(hostname: "www.google.com")
}
catch {
switch error as? Network.Error {
case let .failedToCreateWith(hostname)?:
print("Network error:\nFailed to create reachability object With host named:", hostname)
case let .failedToInitializeWith(address)?:
print("Network error:\nFailed to initialize reachability object With address:", address)
case .failedToSetCallout?:
print("Network error:\nFailed to set callout")
case .failedToSetDispatchQueue?:
print("Network error:\nFailed to set DispatchQueue")
case .none:
print(error)
}
}
return true
}
}

And a view controller sample:

import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default
.addObserver(self,
selector: #selector(statusManager),
name: .flagsChanged,
object: nil)
updateUserInterface()
}
func updateUserInterface() {
switch Network.reachability.status {
case .unreachable:
view.backgroundColor = .red
case .wwan:
view.backgroundColor = .yellow
case .wifi:
view.backgroundColor = .green
}
print("Reachability Summary")
print("Status:", Network.reachability.status)
print("HostName:", Network.reachability.hostname ?? "nil")
print("Reachable:", Network.reachability.isReachable)
print("Wifi:", Network.reachability.isReachableViaWiFi)
}
@objc func statusManager(_ notification: Notification) {
updateUserInterface()
}
}

Sample Project

Which is the simplest way to check for Internet connection in iOS?

Take a look at the Reachability Example provided by Apple.

The problem your approach may have is that you could have a timeout and thus, the synchronized download of some data may block your app. As a result Apple may reject your app.

The Reachability Example can be used as follows:

Reachability *_reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus remoteHostStatus = [_reachability currentReachabilityStatus];
if (remoteHostStatus == NotReachable) {
// not reachable
} else if (remoteHostStatus == ReachableViaWiFi) {
// reachable via Wifi
} else if (remoteHostStatus == ReachableViaWWAN) {
// reachable via WWAN
}

iphone SDK detect Wifi and Carrier network

That sample is exactly what you need.

Look at Reachability.m. it'll tell you whether you have any connection, and then tell you what kind of connection you have.

Check for Internet connection using the iOS SDK

Best way is to use Reachability code. Check here for apple sample code. That has a lot of convenience methods to check internet availability, Wifi/WAN connectivity check etc..

For eg:-

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChanged:) name:kReachabilityChangedNotification object:nil];

reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];

- (void)networkChanged:(NSNotification *)notification
{

NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];

if(remoteHostStatus == NotReachable) { NSLog(@"not reachable");}
else if (remoteHostStatus == ReachableViaWiFiNetwork) { NSLog(@"wifi"); }
else if (remoteHostStatus == ReachableViaCarrierDataNetwork) { NSLog(@"carrier"); }
}

Easiest way to detect Internet connection on iOS?

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.

Check internet connection (iOS 10)

import Foundation
import SystemConfiguration

func isInternetAvailable() -> 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.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}

This works in iOS 10

Detecting Network Connectivity Changes using Reachability, NSNotification and Network Link Conditioner in Swift

You must create a Reachability object before you can receive notifications from it. Also, be sure to call the startNotifier() method on the Reachability object you create. This would be an example of how to do so inside of your application delegate:

class AppDelegate: UIResponder, UIApplicationDelegate
{
private var reachability:Reachability!;

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool
{
NSNotificationCenter.defaultCenter().addObserver(self, selector:"checkForReachability:", name: kReachabilityChangedNotification, object: nil);

self.reachability = Reachability.reachabilityForInternetConnection();
self.reachability.startNotifier();
}

@objc func checkForReachability(notification:NSNotification)
{
// Remove the next two lines of code. You cannot instantiate the object
// you want to receive notifications from inside of the notification
// handler that is meant for the notifications it emits.

//var networkReachability = Reachability.reachabilityForInternetConnection()
//networkReachability.startNotifier()

let networkReachability = notification.object as Reachability;
var remoteHostStatus = networkReachability.currentReachabilityStatus()

if (remoteHostStatus.value == NotReachable.value)
{
println("Not Reachable")
}
else if (remoteHostStatus.value == ReachableViaWiFi.value)
{
println("Reachable via Wifi")
}
else
{
println("Reachable")
}
}
}

I recommend you take a look at the documentation for NSNotificationCenter and NSNotification. That way you'll be more familiar with how to work with notifications next time something like this comes up.

Swift 3

NotificationCenter.default.addObserver(self, selector:Selector(("checkForReachability:")), name: NSNotification.Name.reachabilityChanged, object: nil)
let reachability: Reachability = Reachability.forInternetConnection()
reachability.startNotifier()


Related Topics



Leave a reply



Submit