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

后端 未结 7 1891
旧巷少年郎
旧巷少年郎 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:54

    Details

    • Xcode 10.2.1 (10E1001), Swift 5

    Prepare

    Edit NSAppTransportSecurity in Info.plist:

    Code:

    NSAppTransportSecurity
        
        NSAllowsArbitraryLoads
    
    

    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.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)")
        }
    }
    

提交回复
热议问题