Handle No Internet Connection Error Before Try to Parse the Result in Alamofire

后端 未结 7 1841
旧巷少年郎
旧巷少年郎 2020-12-30 03:04

How should I handle if there is an error occurs when there is no internet connection in Alamofire. I tried checking if data is nil or not but it does not work.

Below

相关标签:
7条回答
  • 2020-12-30 03:34

    This works for me in Swift2.x

    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
                }
        }
    }
    
    0 讨论(0)
  • 2020-12-30 03:40

    Swift 5.0

    You can check with NSURL-related Error Code

    if error._code == NSURLErrorNotConnectedToInternet {
                            
    }
    

    Or you can check with the code

    if error._code == -1009 {
                            
    }
    

    You can check other code on the developer site. https://developer.apple.com/documentation/foundation/1508628-url_loading_system_error_codes

    0 讨论(0)
  • 2020-12-30 03:52

    Swift 3 Solution

    Assuming you have an Error instance you can do the following:

    if let err = error as? URLError, err.code  == URLError.Code.notConnectedToInternet
    {
        // No internet
    }
    else
    {
        // Other errors
    }
    

    You simply cast error into a URLError. This works since URLError implements the Error protocol. Here is a quote from the apple documentation for reference:

    URLError: Describes errors in the URL error domain.

    Once you have a URLError instance you can simply compare its code property, which is a URLError.Code enum, against the any relevant enum cases (in our example URLError.Code.notConnectedToInternet).

    0 讨论(0)
  • 2020-12-30 03:53

    I agree with @Shripada. First you should use Reachability to check for connectivity. There is a Swift library here: https://github.com/ashleymills/Reachability.swift

    additionally you can use one of the Alamofire validation methods:

    Alamofire.request(.POST, REGISTER_URL, parameters: parameters, encoding: .JSON, headers: getAuthenticationHeader()).validate(statusCode: 200 ..< 300).response { (request, response, data, error) -> Void in
        if error != nil {
            println("Server responded with: \(response.statusCode)")
            return
        }
    
        // Handle your response data here
    }
    
    0 讨论(0)
  • 2020-12-30 03:53

    It works in swift 5

    .catchError { (error: Error) in
        if let err = error as? URLError, err.code  == URLError.Code.notConnectedToInternet {
            // No internet
        } else {
            // Other errors
        }
    }
    
    0 讨论(0)
  • 2020-12-30 03:54

    Details

    • Xcode 10.2.1 (10E1001), Swift 5

    Prepare

    Edit NSAppTransportSecurity in Info.plist:

    Code:

    <key>NSAppTransportSecurity</key>
        <dict>
        <key>NSAllowsArbitraryLoads</key><true/>
    </dict>
    

    Sample 1 (need Alamofire pod)

    Use Network Reachability

    import UIKit
    import Alamofire
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let button = UIButton(frame: .init(x: 80, y: 80, width: 100, height: 40))
            button.setTitle("Check", for: .normal)
            button.addTarget(self, action: #selector(checkInternetConnection), for: .touchUpInside)
            button.setTitleColor(.blue, for: .normal)
            view.addSubview(button)
        }
    
        @objc func checkInternetConnection() {
            guard let networkReachabilityManager = NetworkReachabilityManager(host: "http://google.com") else { return }
            networkReachabilityManager.listener = { [weak self] status in
                let alert = UIAlertController(title: "Network Status ", message: "\(status)", preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] _ in
                    alert?.dismiss(animated: true, completion: nil)
                }))
                self?.present(alert, animated: true, completion: nil)
            }
            networkReachabilityManager.startListening()
        }
    }
    

    Sample 2 (need Alamofire pod)

    import UIKit
    import Alamofire
    
    class ViewController: UIViewController {
    
        private lazy var networkManager = NetworkManager()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let button = UIButton(frame: .init(x: 80, y: 80, width: 100, height: 40))
            button.setTitle("Check", for: .normal)
            button.addTarget(self, action: #selector(checkInternetConnection), for: .touchUpInside)
            button.setTitleColor(.blue, for: .normal)
            view.addSubview(button)
        }
    
        @objc func checkInternetConnection() {
            let urlString = "http://dummy.restapiexample.com/api/v1/employees"
            networkManager.sessionManager.request(urlString).validate().response { response in
                print("\(response.data as Any)")
            }
        }
    }
    
    
    class NetworkManager {
        lazy var sessionManager: SessionManager = {
            let configuration = URLSessionConfiguration.default
            configuration.httpCookieStorage = nil
            configuration.httpCookieAcceptPolicy = HTTPCookie.AcceptPolicy.never
            let manager = SessionManager(configuration: configuration)
            manager.retrier = self
            return manager
        }()
    }
    
    extension NetworkManager: RequestRetrier {
        func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
            let error = error as NSError
            switch error.code {
                case -1009:
                    DispatchQueue.main.async {
                        let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
                        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] _ in
                            alert?.dismiss(animated: true, completion: nil)
                        }))
                        UIApplication.topMostViewController?.present(alert, animated: true, completion: nil)
                    }
                default: break
            }
            print("-- Error code: \(error.code)")
            print("-- Error descriptiom: \(error.localizedDescription)")
        }
    }
    
    
    // https://stackoverflow.com/a/52932487
    extension UIViewController {
        var topMostViewController: UIViewController {
    
            if let presented = self.presentedViewController {
                return presented.topMostViewController
            }
    
            if let navigation = self as? UINavigationController {
                return navigation.visibleViewController?.topMostViewController ?? navigation
            }
    
            if let tab = self as? UITabBarController {
                return tab.selectedViewController?.topMostViewController ?? tab
            }
            return self
        }
    }
    
    extension UIApplication {
        class var topMostViewController : UIViewController? {
            return UIApplication.shared.keyWindow?.rootViewController?.topMostViewController
        }
    }
    

    Sample 3 (without third party library)

    More info: How to use SCNetworkReachability in Swift

    import UIKit
    import SystemConfiguration
    
    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            let button = UIButton(frame: .init(x: 80, y: 80, width: 100, height: 40))
            button.setTitle("Check", for: .normal)
            button.addTarget(self, action: #selector(checkInternetConnection), for: .touchUpInside)
            button.setTitleColor(.blue, for: .normal)
            view.addSubview(button)
        }
    
        @objc func checkInternetConnection() {
            print("-- \(URLSession.connectedToNetwork())")
        }
    }
    
    extension URLSession {
        class func connectedToNetwork() -> Bool {
            var zeroAddress = sockaddr()
            zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
            zeroAddress.sa_family = sa_family_t(AF_INET)
            guard let networkReachability = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else { return false }
            var flags = SCNetworkReachabilityFlags()
            SCNetworkReachabilitySetDispatchQueue(networkReachability, DispatchQueue.global(qos: .default))
            if SCNetworkReachabilityGetFlags(networkReachability, &flags) == false { return false }
            let isReachable = flags.contains(.reachable)
            let needsConnection = flags.contains(.connectionRequired)
            return isReachable && !needsConnection
        }
    }
    

    Sample 4 (need Reachability.swift pod)

    import UIKit
    import Reachability
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let button = UIButton(frame: .init(x: 80, y: 80, width: 100, height: 40))
            button.setTitle("Check", for: .normal)
            button.addTarget(self, action: #selector(checkInternetConnection), for: .touchUpInside)
            button.setTitleColor(.blue, for: .normal)
            view.addSubview(button)
        }
    
        @objc func checkInternetConnection() {
            guard let reachability = Reachability(hostname: "google.com", queueQoS: .utility) else { return }
            try? reachability.startNotifier()
            print("-- \(reachability.connection as Any)")
        }
    }
    
    0 讨论(0)
提交回复
热议问题