user7418039
user7418039

Reputation: 311

Check iOS app internet connection after app is launched

I am making an app which requires API requests. If there's no internet connection in any way (mobile connection, wifi, etc), there's no usage in my app. So I'm trying to populate activity indicator view whenever there's no internet connection in my app.

I found really good Stack Overflow post which let me check the connection status of my device (Check for internet connection with Swift).

However, here is one thing I'm not sure. If I put a method to check iOS device's network connectivity in AppDelegate didFinishLaunchingWithOptions method, then it will be only checked when the app is launched, right? I want to show the activity indicator view whenever there is no connection. In order to facilitate this feature, I would like to know which place makes the most sense to put the method in the app.

Upvotes: 0

Views: 1764

Answers (5)

Yogesh Tandel
Yogesh Tandel

Reputation: 1754

Create below 2 class files Singleton Class

import Foundation
import UIKit

class Constants:NSObject{


    let defaults = UserDefaults.standard
    var isNetworkon:Bool?



    override init() {
        super.init()
        CLIENTKEY = ""
    }

    class var sharedInstance: Constants {
        struct Singleton {
            static let instance = Constants()
        }
        return Singleton.instance
    }

    func checkNetwork(vc:UIViewController) -> Bool {
        NotificationCenter.default.addObserver(self, selector: #selector(networkStatusChanged(_:)), name: NSNotification.Name(rawValue: ReachabilityStatusChangedNotification), object: nil)
        Reach().monitorReachabilityChanges()


        let status = Reach().connectionStatus()
        switch status {
        case .unknown, .offline:
            print("Not connected")
            MyCustomAlert .sharedInstance.ShowAlert(vc: vc, myTitle: "No Internet Connection", myMessage: "Make sure your device is connected to the internet.")
            isNetworkon = false;
        case .online(.wwan):
            print("Connected via WWAN")
            isNetworkon = true;
        case .online(.wiFi):
            print("Connected via WiFi")
            isNetworkon = true;
        }
        return isNetworkon!;
    }

    @objc func networkStatusChanged(_ notification: Notification) {
        let userInfo = (notification as NSNotification).userInfo
        print(userInfo?.capacity)
    }


}

Reach Class

    import Foundation
import SystemConfiguration


let ReachabilityStatusChangedNotification = "ReachabilityStatusChangedNotification"

enum ReachabilityType: CustomStringConvertible {
    case wwan
    case wiFi

    var description: String {
        switch self {
        case .wwan: return "WWAN"
        case .wiFi: return "WiFi"
        }
    }
}

enum ReachabilityStatus: CustomStringConvertible  {
    case offline
    case online(ReachabilityType)
    case unknown

    var description: String {
        switch self {
        case .offline: return "Offline"
        case .online(let type): return "Online (\(type))"
        case .unknown: return "Unknown"
        }
    }
}

public class Reach {

    func connectionStatus() -> ReachabilityStatus {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(nil, $0)
            }
        }) else {
            return .unknown
        }

        var flags : SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return .unknown
        }

        return ReachabilityStatus(reachabilityFlags: flags)
    }


    func monitorReachabilityChanges() {
        let host = "holidaycenterglobal.com"
        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        let reachability = SCNetworkReachabilityCreateWithName(nil, host)!

        SCNetworkReachabilitySetCallback(reachability, { (_, flags, _) in
            let status = ReachabilityStatus(reachabilityFlags: flags)

            NotificationCenter.default.post(name: Notification.Name(rawValue: ReachabilityStatusChangedNotification),
                                            object: nil,
                                            userInfo: ["Status": status.description])

            }, &context)

        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), RunLoopMode.commonModes as CFString)
    }

}

extension ReachabilityStatus {
    init(reachabilityFlags flags: SCNetworkReachabilityFlags) {
        let connectionRequired = flags.contains(.connectionRequired)
        let isReachable = flags.contains(.reachable)
        let isWWAN = flags.contains(.isWWAN)

        if !connectionRequired && isReachable {
            if isWWAN {
                self = .online(.wwan)
            } else {
                self = .online(.wiFi)
            }
        } else {
            self =  .offline
        }
    }
}

Access it using

if(Constants.sharedInstance.checkNetwork(vc: self)){
 // Call api here
}

Upvotes: 1

Mina
Mina

Reputation: 2212

Swift 3: You can use the following class to check network reachability:

import Foundation
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)
    }
}

Usage:

guard Reachability.isConnectedToNetwork() else {
            completion({ throw Errors.Network.noInternet(message: "No internet connection")  })
            return
}

Upvotes: 0

Developer
Developer

Reputation: 832

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
 ........

 internetReachable = [Reachability reachabilityForInternetConnection];
    [internetReachable startNotifier];
 [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(checkInternetConnectionStatus:)
                                                 name:kReachabilityChangedNotification object:nil];
............

}

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

    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
    switch (internetStatus)
    {
        case NotReachable:
        {
            NSLog(@"No active internet connection");
            break;
        }
        case ReachableViaWiFi:
        {
             NSLog(@"The internet is Connected.");
            break;
        }
        case ReachableViaWWAN:
        {
            NSLog(@"The internet is working via WWAN!");
            break;
        }
    }
}

Use apple's Reachability class

if you want to check manually then

 class func isConnectedToNetwork() -> Bool {

        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        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 = SCNetworkReachabilityFlags(rawValue: 0)
        if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
            return false
        }

        let isReachable = flags == .reachable
        let needsConnection = flags == .connectionRequired

        return isReachable && !needsConnection

    }



    if self.isConnectedToNetwork() == true
{
//make API call
}
else
{
//Display alert(No internet connection)
}

Upvotes: 0

elk_cloner
elk_cloner

Reputation: 2149

There is a great library not for using this.It's only tiny part of this library. use alamofire

How?

you can check reachibility by using this code only.

let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.apple.com")

func listenForReachability() {
    self.reachabilityManager?.listener = { status in
        print("Network Status Changed: \(status)")
        switch status {
        case .NotReachable:
            //Show error state
        case .Reachable(_), .Unknown:
            //Hide error state
        }
    }

    self.reachabilityManager?.startListening()
}

You may using this code as a singleton. Remember to hold on to the reachability manager reference.

Upvotes: 3

Muhammed
Muhammed

Reputation: 586

For swift 3

import SystemConfiguration


public func isConnectedToNetwork() -> Bool {
    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
    zeroAddress.sin_family = sa_family_t(AF_INET)

    guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
            SCNetworkReachabilityCreateWithAddress(nil, $0)
        }
    }) else {
        return false
    }

    var flags: SCNetworkReachabilityFlags = []
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
        return false
    }

    let isReachable = flags.contains(.reachable)
    let needsConnection = flags.contains(.connectionRequired)

    return (isReachable && !needsConnection)
}

then check :

if isConnectedToNetwork() 
{
// connected 

}else 
{
// not  connected 
}

Upvotes: 1

Related Questions