检查Swift中的互联网连接可用性



是否有办法检查互联网连接是否可用使用Swift?

我知道有很多第三方库可以做到这一点,但它们都是用Objective-C编写的。我正在寻找一个Swift的替代品。

正如评论中提到的,虽然在Swift中可以使用Objective-C库,但我想要一个更纯粹的Swift解决方案。现有的Apple Reachability类和其他第三方库似乎太复杂了,我无法将其翻译成Swift。我在谷歌上搜索了更多,发现了这篇文章,它展示了一种检查网络可用性的简单方法。我开始把这句话翻译给斯威夫特听。我遇到了很多障碍,但多亏了StackOverflow的Martin R,我设法解决了它们,并最终在Swift中得到了一个可行的解决方案。代码如下:

import Foundation
import SystemConfiguration
public class Reachability {
    class func isConnectedToNetwork() -> Bool {
        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)
        let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)).takeRetainedValue()
        }
        var flags: SCNetworkReachabilityFlags = 0
        if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == 0 {
            return false
        }
        let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        return isReachable && !needsConnection
    }
}

For Swift> 3.0

public class Reachability {
    public func isConnectedToNetwork() -> Bool {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)
        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(nil, $0)
            }
        }) else {
            return false
        }
        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return false
        }
        if flags.isEmpty {
            return false
        }
        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)
        return (isReachable && !needsConnection)
    }
}

这适用于3G和WiFi连接。我还把它上传到我的GitHub与一个工作示例。

3.1斯威夫特(iOS 10.1)

如果要区分网络类型(即WiFi或WWAN):

你可以使用:

func checkWiFi() -> Bool {
    let networkStatus = Reachability().connectionStatus()
    switch networkStatus {
    case .Unknown, .Offline:
        return false
    case .Online(.WWAN):
        print("Connected via WWAN")
        return true
    case .Online(.WiFi):
        print("Connected via WiFi")
        return true
    }
}

这是区分网络类型的整个可达性类:

import Foundation
import SystemConfiguration
import UIKit
import SystemConfiguration.CaptiveNetwork
public let ReachabilityStatusChangedNotification = "ReachabilityStatusChangedNotification"
public enum ReachabilityType: CustomStringConvertible {
    case WWAN
    case WiFi
    public var description: String {
        switch self {
        case .WWAN: return "WWAN"
        case .WiFi: return "WiFi"
        }
    }
}
public enum ReachabilityStatus: CustomStringConvertible  {
    case Offline
    case Online(ReachabilityType)
    case Unknown
    public var description: String {
        switch self {
        case .Offline: return "Offline"
        case .Online(let type): return "Online ((type))"
        case .Unknown: return "Unknown"
        }
    }
}
public class Reachability {
    func connectionStatus() -> ReachabilityStatus {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)
        guard let defaultRouteReachability = (withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) { zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }) else {
           return .Unknown
        }
        var flags : SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return .Unknown
        }
        return ReachabilityStatus(reachabilityFlags: flags)
    }
    func monitorReachabilityChanges() {
        let host = "google.com"
        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        let reachability = SCNetworkReachabilityCreateWithName(nil, host)!
        SCNetworkReachabilitySetCallback(reachability, { (_, flags, _) in
            let status = ReachabilityStatus(reachabilityFlags: flags)
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: ReachabilityStatusChangedNotification), object: nil, userInfo: ["Status": status.description])}, &context)
        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
    }
}
extension ReachabilityStatus {
    public init(reachabilityFlags flags: SCNetworkReachabilityFlags) {
        let connectionRequired = flags.contains(.connectionRequired)
        let isReachable = flags.contains(.reachable)
        let isWWAN = flags.contains(.isWWAN)
        if !connectionRequired && isReachable {
            if isWWAN {
                self = .Online(.WWAN)
            } else {
                self = .Online(.WiFi)
            }
        } else {
            self =  .Offline
        }
    }
}

我给你更好的方法…

你必须用下面的代码创建一个类

 import Foundation
 public class Reachability {
class func isConnectedToNetwork()->Bool{
    var Status:Bool = false
    let url = NSURL(string: "http://google.com/")
    let request = NSMutableURLRequest(URL: url!)
    request.HTTPMethod = "HEAD"
    request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
    request.timeoutInterval = 10.0
    var response: NSURLResponse?
    var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) as NSData?
    if let httpResponse = response as? NSHTTPURLResponse {
        if httpResponse.statusCode == 200 {
            Status = true
        }
    }
    return Status
  }
}

然后你可以在你的项目中使用以下代码检查网络连接:

if Reachability.isConnectedToNetwork() == true {
     println("Internet connection OK")
} else {
     println("Internet connection FAILED")
}

非常简单!

*这个方法是基于Vikram Pote的答案!

SWIFT 3:检查wifiinternet连接:

import Foundation
import SystemConfiguration
public class Reachability {
    public func isConnectedToNetwork() -> Bool {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)
        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(nil, $0)
            }
        }) else {
            return false
        }
        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return false
        }
        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)
        return (isReachable && !needsConnection)
    }
}

用法:

if Reachability.isConnectedToNetwork() == true {
    print("Connected to the internet")
    //  Do something
} else {
    print("No internet connection")
    //  Do something
}

由于sendSynchronousRequest已弃用,我尝试了这个,但在响应完成之前调用了'返回状态'。

这个答案很好,检查一下Swift的网络连接

我是这么做的:

import Foundation
public class Reachability {
    class func isConnectedToNetwork()->Bool{
        var Status:Bool = false
        let url = NSURL(string: "http://google.com/")
        let request = NSMutableURLRequest(URL: url!)
        request.HTTPMethod = "HEAD"
        request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
        request.timeoutInterval = 10.0
        let session = NSURLSession.sharedSession()
        session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
            print("data (data)")
            print("response (response)")
            print("error (error)")
            if let httpResponse = response as? NSHTTPURLResponse {
                print("httpResponse.statusCode (httpResponse.statusCode)")
                if httpResponse.statusCode == 200 {
                    Status = true
                }
            }
        }).resume()

        return Status
    }
}

你也可以用下面的答案。

    func checkInternet(flag:Bool, completionHandler:(internet:Bool) -> Void)
    {
      UIApplication.sharedApplication().networkActivityIndicatorVisible = true
      let url = NSURL(string: "http://www.google.com/")
      let request = NSMutableURLRequest(URL: url!)
      request.HTTPMethod = "HEAD"
      request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
      request.timeoutInterval = 10.0
      NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.mainQueue(), completionHandler:
      {(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false
        let rsp = response as NSHTTPURLResponse?
        completionHandler(internet:rsp?.statusCode == 200)
    })
    }
     func yourMethod()
    {
    self.checkInternet(false, completionHandler:
    {(internet:Bool) -> Void in
        if (internet)
        {
            // "Internet" mean Google
        }
        else
        {
            // No "Internet" no Google
        }
    })
   }

迅速5:

import Network
let monitor = NWPathMonitor()
func checkInterwebs() -> Bool {
    var status = false
    monitor.pathUpdateHandler = { path in
        if path.status == .satisfied {
            status = true  // online
        }
    }
    return status
}

Swift 4

if isInternetAvailable() {
    print("if called Internet Connectivity success (isInternetAvailable())");
} else {
    print("else called Internet Connectivity success (isInternetAvailable())");
}
func isInternetAvailable() -> 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)
     }
    }
   var flags = SCNetworkReachabilityFlags()
   if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
      return false
   }
   let isReachable = flags.contains(.reachable)
   let needsConnection = flags.contains(.connectionRequired)
   //   print(isReachable && !needsConnection)
   return (isReachable && !needsConnection)
}

如果您在项目中使用Alamofire,您可以使用以下示例函数:

import Alamofire
class Network {
    func isConnected(_ complition: @escaping(Bool) -> Void) {
        let retVal = NetworkReachabilityManager()!.isReachable
        complition(retVal)
    }
}

如果你只是想知道它是否连接并且你正在使用SwiftUI:

服务:

import Foundation
import Network
class ConnectionService: ObservableObject {
    @Published var connected: Bool = false
    
    private var monitor: NWPathMonitor
    
    init() {
        monitor = NWPathMonitor()
        monitor.pathUpdateHandler = { [weak self] path in
            switch path.status {
            case .satisfied:
                self?.connected = true
            case .unsatisfied, .requiresConnection:
                self?.connected = false
            @unknown default:
                self?.connected = false
            }
        }
        monitor.start(queue: DispatchQueue.main)
    }
}

用法:

// step 1: add in your App struct
@StateObject var internet = ConnectionService() 
// step 2: add this modifier to your top level view
.environmentObject(internet) 
// step 3: add this in any child view
@EnvironmentObject var internet: ConnectionService 
// step 4: example usage in that child view
Text("internet: (internet.connected ? "true" : "false")") 

SWIFT 3:检查3G &wi - fi连接

DispatchQueue.main.async {
        let url = URL(string: "https://www.google.com")!
        let request = URLRequest(url: url)
        let task = URLSession.shared.dataTask(with: request) {data, response, error in
            if error != nil {
                // do something here...
                print("Internet Connection not Available!")
            }
            else if let httpResponse = response as? HTTPURLResponse {
                if httpResponse.statusCode == 200 {
                    // do something here...
                    print("Internet Connection OK")
                }
                print("statusCode: (httpResponse.statusCode)")
            }
        }
        task.resume()
}

最新更新