35

I am using below code for making HTTP request in server.Now I want to know whether it is connected to internet or not. Below is my code

  let request = Alamofire.request(completeURL(domainName: path), method: method, parameters: parameters, encoding: encoding.value, headers: headers)
      .responseJSON {


        let resstr = NSString(data: $0.data!, encoding: String.Encoding.utf8.rawValue)
        print("error is \(resstr)")


        if $0.result.isFailure {
          self.failure("Network")
          print("API FAILED 4")
          return
        }
        guard let result = $0.result.value else {
          self.unKnownError()
          self.failure("")
          print("API FAILED 3")

          return
        }
        self.handleSuccess(JSON(result))
    }
Honey
  • 24,125
  • 14
  • 123
  • 212
TechChain
  • 7,104
  • 20
  • 81
  • 193
  • you can use [network reachability](https://github.com/Alamofire/Alamofire#network-reachability) – Hamza Ansari Dec 26 '16 at 06:53
  • You might want to check [this answer](http://stackoverflow.com/a/32187515/5501940) – Ahmad F Dec 26 '16 at 07:10
  • Possible duplicate of [Check Internet connection availability?](http://stackoverflow.com/questions/32185705/check-internet-connection-availability) – TajyMany Jan 18 '17 at 08:15

8 Answers8

97

For swift 3.1 and Alamofire 4.4 ,I created a swift class called Connectivity . Use NetworkReachabilityManager class from Alamofire and configure the isConnectedToInternet() method as per your need.

import Foundation
import Alamofire

class Connectivity {
    class func isConnectedToInternet() -> Bool {
        return NetworkReachabilityManager()?.isReachable ?? false
    }
}

Usage:

if Connectivity.isConnectedToInternet() {
        print("Yes! internet is available.")
        // do some tasks..
 }

EDIT: Since swift is encouraging computed properties, you can change the above function like:

import Foundation
import Alamofire
class Connectivity {
    class var isConnectedToInternet:Bool {
        return NetworkReachabilityManager()?.isReachable ?? false
    }
}

and use it like:

if Connectivity.isConnectedToInternet {
        print("Yes! internet is available.")
        // do some tasks..
 }
abhimuralidharan
  • 5,093
  • 2
  • 42
  • 63
  • Simple, working and reusable. Don't know though if is better to make it a protocol with extension and override in needed places. – Andreas777 Apr 04 '17 at 08:05
  • I've never used `class var`. What's the difference of doing that and `shared let`? I know their different. Just not sure how! – Honey May 23 '18 at 04:28
  • 1
    I just made a computed variable that can be called on a class type directly. You can also use static which is better in this case. What do you mean by shared let? – abhimuralidharan May 23 '18 at 06:32
  • 2
    This actually does not work. This just checks whether mobile data or wifi is or or not. It does not check whether the "actual internet" is available or not. Create a hotspot without internet. it will say its connected. – Anuran Barman Jun 14 '19 at 13:20
23

Swift 2.3

Alamofire.request(.POST, url).responseJSON { response in
switch response.result {
    case .Success(let json):
        // internet works.  
    case .Failure(let error):

        if let err = error as? NSURLError where err == .NotConnectedToInternet {
            // no internet connection
        } else {
            // other failures
        }
    }
}

Swift 3.0

  Alamofire.upload(multipartFormData: { multipartFormData in
    }, to: URL, method: .post,headers: nil,
       encodingCompletion:  { (result) in
        switch result {

        case .success( _, _, _): break

        case .failure(let encodingError ):
            print(encodingError)

            if let err = encodingError as? URLError, err.code == .notConnectedToInternet {
                // no internet connection
                print(err)
            } else {
                // other failures
            }

        }
    })

Using NetworkReachabilityManager

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

func checkForReachability() {
    self.networkReachabilityManager?.listener = { status in
        print("Network Status: \(status)")
        switch status {
        case .notReachable:
            //Show error here (no internet connection)
        case .reachable(_), .unknown:
            //Hide error here
        }
    }

    self.networkReachabilityManager?.startListening()
}

//How to Use : Just call below function in required class
if checkForReachability() {
   print("connected with network")
}
MAhipal Singh
  • 4,220
  • 35
  • 53
  • Everytime i call this function for the first time it gives .reachable true no matter what the state of the internet connect is – PersianBlue Mar 20 '19 at 10:53
18

For Swift 3/4,

In Alamofire, there is a class called NetworkReachabilityManager which can be used to observer or check if internet is available or not.

let reachabilityManager = NetworkReachabilityManager()

reachabilityManager?.startListening()
reachabilityManager?.listener = { _ in
        if let isNetworkReachable = self.reachabilityManager?.isReachable,
            isNetworkReachable == true {
            //Internet Available
        } else {
            //Internet Not Available"
        }
    }

Here, listener will get called every time when there is changes in state of internet. You can handle it as you would like.

Parth Adroja
  • 11,417
  • 5
  • 35
  • 65
  • 1
    And does the reachabilityManager need to be deinitialised in deint() ? – Sujal Jun 05 '18 at 09:33
  • 1
    @Sujal Depends on your use case if you want it into whole application then not needed as you would declare in AppDelegate. If your use case is single shot then you can deinit NetworkReachabilityManager. – Parth Adroja Jun 05 '18 at 10:53
  • 2
    Out of all the many answers on the internet, this is the one that worked for me. (Note, that it doesn't work perfectly in the simulator, but on an actual phone it works perfectly.) – Derence Jun 16 '19 at 17:53
2

If you goto NetworkReachabilityManager.swift you will see this

/// Whether the network is currently reachable. public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }

So I have written this in my APIhandlerClass

import AlamofireNetworkActivityIndicator

private let manager = NetworkReachabilityManager(host: "www.apple.com")

func isNetworkReachable() -> Bool {
    return manager?.isReachable ?? false
}

So this tells me the status of network.

Umair Afzal
  • 4,398
  • 5
  • 22
  • 46
2

If Alamofire.upload result returns success then below is the way to check for internet availibility while uploading an image:

Alamofire.upload(multipartFormData: { multipartFormData in

                for (key,value) in parameters {
                 multipartFormData.append((value).data(using: .utf8)!, withName: key)
                }
                  multipartFormData.append(self.imageData!, withName: "image" ,fileName: "image.jpg" , mimeType: "image/jpeg")
            }, to:url)
            { (result) in

                switch result{

                case .success(let upload, _, _):

                    upload.uploadProgress(closure: { (progress) in
                     print("Upload Progress: \(progress.fractionCompleted)")

                    })

                    upload.responseJSON { response in
                        if  let statusCode = response.response?.statusCode{

                        if(statusCode == 201){
                         //internet available
                          }
                        }else{
                        //internet not available

                        }
                    }

                case .failure(let encodingError):
                    print(encodingError)

                }

            }
Nupur Sharma
  • 828
  • 9
  • 13
2

In general if you can get the internet offline information from the actual call, its better than reachability. You can be certain that the actual API call has failed because the internet is down. If you test for reachability before you call an API and it fails then all you know is that when the test was done the internet was offline ( or Apple was down), you don't know that when you make the call the internet will be offline. You might think it is a matter of milliseconds after the reachability call returns, or you retrieved the stored value, but thats in fact non deterministic. The OS might have scheduled some arbitrary number of threads before reachability returns its values in its closure, or updates whatever global you are storing.

And reachability has historically had bugs in its own code.

This isn't to say that you shouldn't use alamofire's NetworkReachabilityManager to change your UI, listen to it and update all the UI components.

But if you have reason to call an API, at that API layer the test for reachability is redundant, or possibly will cause some subtle bugs.

1
  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)
        }
    }
    //Commented code only work upto iOS Swift 2.3
    //    let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
    //
    //        SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
    //    }

    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)
}
    // Call api method
    func callApi(){
        if isConnectedToNetwork() {  // Network Connection status
            // Call your request here
        }else{
            //"Your Internet connection is not active at this time."
        }
    }
MAhipal Singh
  • 4,220
  • 35
  • 53
  • I want to do it by alamofire not reachibilty – TechChain Dec 26 '16 at 07:36
  • let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.apple.com") func listenForReachability() { reachabilityManager?.listener = { status in print("Network Status Changed: \(status)") switch status { case .NotReachable: break //Show error state case .Reachable(_), .Unknown: break //Hide error state } } reachabilityManager?.startListening() } – MAhipal Singh Dec 26 '16 at 07:55
  • i cant follow this approach please review my code & provide solution – TechChain Dec 26 '16 at 07:56
1

Using RequestAdapter class of alamofire and throw error when no internet connectivity

class RequestInterceptor : RequestAdapter{
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {

    let reachable = NetworkReachabilityManager()?.isReachable ?? false
    if !reachable{
        throw NSError.NoInternet
    }
    var nUrlRequest = urlRequest
    // modify request if needed 
    return nUrlRequest
   }
}

extension NSError  {

static func createWithLocalizedDesription(withCode code:Int = 204,localizedDescription:String) -> NSError{
    return  NSError(domain: "<your bundle id>", code:code, userInfo: [NSLocalizedDescriptionKey : localizedDescription])
}
static var NoInternet : NSError {
    return createWithLocalizedDesription(withCode: -1009,localizedDescription:"Please check your internet connection")
}

}

Now set the adapter to Alamofire Session Manager

let sessionManager = Alamofire.SessionManager(configuration: configuration)

sessionManager.adapter = RequestInterceptor()

Now each time when You create Alamofire Request, catch the error in DataResponse. This mechanism will act common to all request

  • 2
    Do NOT use Reachability to determine if a network request should be sent. You should ALWAYS send it. ref: https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#network-reachability – Ted Jan 26 '19 at 10:51