【问题标题】:How to check internet connection in alamofire?如何在alamofire中检查互联网连接?
【发布时间】:2017-05-10 16:29:25
【问题描述】:

我正在使用下面的代码在服务器中发出 HTTP 请求。现在我想知道它是否连接到互联网。下面是我的代码

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

【问题讨论】:

标签: ios swift alamofire reachability


【解决方案1】:

对于 swift 3.1 和 Alamofire 4.4,我创建了一个名为 Connectivity 的 swift 类。根据您的需要使用Alamofireconfigure 中的NetworkReachabilityManager 类和isConnectedToInternet() 方法。

import Foundation
import Alamofire

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

用法:

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

编辑: 由于 swift 鼓励计算属性,您可以将上述函数更改为:

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

并像这样使用它:

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

【讨论】:

  • 简单、有效且可重复使用。不知道是否最好将其作为扩展协议并在需要的地方覆盖。
  • 我从未使用过class var。这样做和shared let 有什么区别?我知道他们的不同。只是不知道怎么做!
  • 我刚刚做了一个计算变量,可以直接在类类型上调用。在这种情况下,您也可以使用更好的静态。共享让是什么意思?
  • 这实际上是行不通的。这只是检查移动数据或wifi是否存在。它不检查“实际互联网”是否可用。创建一个没有互联网的热点。它会说它已连接。
【解决方案2】:

斯威夫特 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
            }

        }
    })

使用 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")
}

【讨论】:

  • 每次我第一次调用这个函数时,无论互联网连接的状态如何,它都会给出 .reachable true
【解决方案3】:

对于 Swift 3/4,

在 Alamofire 中,有一个名为 NetworkReachabilityManager 的类,可用于观察或检查互联网是否可用。

let reachabilityManager = NetworkReachabilityManager()

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

在这里,每当互联网状态发生变化时,都会调用监听器。你可以随心所欲地处理它。

【讨论】:

  • 那么reachabilityManager 需要在deint() 中取消初始化吗?
  • @Sujal 取决于您的用例,如果您希望它进入整个应用程序然后不需要,因为您将在 AppDelegate 中声明。如果您的用例是单次的,那么您可以取消初始化 NetworkReachabilityManager。
  • 在互联网上的所有答案中,这是对我有用的一个。 (请注意,它在模拟器中无法完美运行,但在实际手机上却可以完美运行。)
【解决方案4】:

如果 Alamofire.upload result 返回成功,那么以下是在上传图片时检查互联网可用性的方法:

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)

                }

            }

【讨论】:

    【解决方案5】:

    一般而言,如果您可以从实际通话中获取互联网离线信息,则比可达性更好。您可以确定实际的 API 调用已失败,因为 Internet 已关闭。如果您在调用 API 之前测试可访问性并且它失败了,那么您所知道的就是当测试完成时互联网处于离线状态(或 Apple 已关闭),您不知道当您 制作 互联网通话将处于离线状态。您可能认为在可达性调用返回后只需几毫秒,或者您检索到存储的值,但这实际上是不确定的。在可达性在其闭包中返回其值或更新您存储的任何全局之前,操作系统可能已经安排了任意数量的线程。

    而可达性历来在其自己的代码中存在错误。

    这并不是说您不应该使用 alamofire 的 NetworkReachabilityManager 来更改您的 UI、监听它并更新所有 UI 组件。

    但如果您有理由调用 API,则在该 API 层,可达性测试是多余的,或者可能会导致一些细微的错误。

    【讨论】:

    • 展示如何切换 AFError 以获取 No internet one only
    【解决方案6】:

    如果你转到 NetworkReachabilityManager.swift 你会看到这个

    /// 网络当前是否可达。 public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }

    所以我在我的 APIhandlerClass 中写了这个

    import AlamofireNetworkActivityIndicator
    
    private let manager = NetworkReachabilityManager(host: "www.apple.com")
    
    func isNetworkReachable() -> Bool {
        return manager?.isReachable ?? false
    }
    

    所以这告诉我网络的状态。

    【讨论】:

    • 请仅在 alamofire 中提供解决方案
    • 它是 alamofire 的一部分
    【解决方案7】:
      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."
            }
        }
    

    【讨论】:

    • 我想通过 alamofire 不可达性来完成
    • 让reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.apple.com") func listenForReachability() {reachabilityManager?.listener = { status in print("Network Status Changed: (status)") switch status { case .NotReachable: break //显示错误状态 case .Reachable(_), .Unknown: break //隐藏错误状态 } }reachabilityManager?.startListening() }
    • 我无法采用这种方法,请查看我的代码并提供解决方案
    【解决方案8】:

    使用RequestAdapter alamofire 类并在没有互联网连接时抛出错误

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

    现在将适配器设置为Alamofire Session Manager

    let sessionManager = Alamofire.SessionManager(configuration: configuration)
    
    sessionManager.adapter = RequestInterceptor()
    

    现在每次创建 Alamofire 请求 时,都会在 DataResponse 中捕获错误。这种机制将适用于所有请求

    【讨论】:

    【解决方案9】:

    在 Alamofire 5 中,当错误为 AFError 类型时,您可以这样切换:

     case .failure(let error):  // error is type of AFError
                        if error.isSessionTaskError {
                          // seems that one only get triggered when no internet 
                            print("Session task error")
                            print(error.localizedDescription)
                            }
                        switch error.responseCode {
                        case 401:
                            print("401 token invalid or expired")
                        default:
                            print("Error : \(error.responseCode ?? 0)")
                            print(error.localizedDescription)
                        }
                        print("All other errors:\(error)")
                    case .finished:
                        break
                    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-05
      • 1970-01-01
      • 2013-02-02
      相关资源
      最近更新 更多