在尝试在 Alamofire 中解析结果之前处理无互联网连接错误

问题描述 投票:0回答:8

Alamofire 无网络连接时出现错误,该如何处理?我尝试检查数据是否为零,但它不起作用。

以下是我如何使用Alamofire

Alamofire.request(.POST, REGISTER_URL, parameters: parameters, encoding: .JSON, headers: getAuthenticationHeader()).response { (request, response, data, errorType) -> Void in

    let resultObject: APIResults = APIResults(JSONDecoder(data!));
    let responseCode: Int = Int(resultObject.code!)!;// THIS CRASHES WHEN THERE IS NO INTERNET CONNECTION

    if (responseCode == 200) {
        available = true;
    }

    finished = true;

}
ios swift swift2 alamofire
8个回答
37
投票

Swift 3 解决方案

假设您有一个

Error
实例,您可以执行以下操作:

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

您只需将

error
转换为
URLError
即可。这是有效的,因为
URLError
实现了
Error
协议。这里引用苹果文档供参考:

URLError:描述 URL 错误域中的错误。

一旦您拥有

URLError
实例,您就可以简单地将其
code
属性(即
URLError.Code
枚举)与任何相关枚举案例进行比较(在我们的示例中为
URLError.Code.notConnectedToInternet
)。


12
投票

这对我来说适用于 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
            }
    }
}

5
投票

我同意@Shripada。首先,您应该使用 Reachability 来检查连接性。 这里有一个 Swift 库:https://github.com/ashleymills/Reachability.swift

此外,您可以使用 Alamofire 验证方法之一:

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
}

5
投票

检查是否存在互联网连接的其他方法

import SystemConfiguration

func connectedToNetwork() -> Bool {

        var zeroAddress = sockaddr_in()    

       zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))

        zeroAddress.sin_family = sa_family_t(AF_INET)

      guard let defaultRouteReachability = withUnsafePointer(&zeroAddress, {
            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
        }) else {
            return false
        }
        var flags : SCNetworkReachabilityFlags = []

        if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == false {

            return false

        }

        let isReachable = flags.contains(.Reachable)

        let needsConnection = flags.contains(.ConnectionRequired)

        return (isReachable && !needsConnection)

    }

let hasInternet = connectedToNetwork()

4
投票

斯威夫特5.0

您可以通过NSURL相关错误代码

进行检查
if error._code == NSURLErrorNotConnectedToInternet {
                        
}

或者您可以通过代码查看

if error._code == -1009 {
                        
}

您可以在开发者网站上查看其他代码。 https://developer.apple.com/documentation/foundation/1508628-url_loading_system_error_codes


3
投票

详情

  • Xcode 10.2.1 (10E1001)、Swift 5

准备

在Info.plist中编辑NSAppTransportSecurity

代码:

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

样品1(需要Alamofire pod)

使用网络可达性

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()
    }
}

样品 2(需要 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
    }
}

示例3(不含第三方库)

更多信息:如何在 Swift 中使用 SCNetworkReachability

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
    }
}

示例 4(需要 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)")
    }
}

1
投票

它可以在 swift 5 中运行

.catchError { (error: Error) in
    if let err = error as? URLError, err.code  == URLError.Code.notConnectedToInternet {
        // No internet
    } else {
        // Other errors
    }
}

0
投票

AFError
类包含返回布尔值的
isSessionTaskError
true
如果出现互联网错误

 public var isSessionTaskError: Bool {
        if case .sessionTaskFailed = self { return true }
        return false
    }

因此,为了处理与互联网相关的错误,您可以这样做

if error.isSessionTaskError {
   // No Internet
}else{
   // Other error
}
© www.soinside.com 2019 - 2024. All rights reserved.