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

Isu*_*uru 105 ios network-connection swift

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

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

Isu*_*uru 222

正如评论中所提到的,尽管可以在Swift中使用Objective-C库,但我想要一个更纯粹的Swift解决方案.现有的Apple Reachability类和其他第三方库似乎太复杂了,我无法翻译成Swift.我用Google搜索了一些,我看到了这篇文章,它展示了一种检查网络可用性的简单方法.我打算将其转换为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
    }

}
Run Code Online (Sandbox Code Playgroud)

对于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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我发现了另一个问题,如果**打开了**但我没有更多的数据容量,那么`isConnectedToNetwork`返回true,**但是我无法调用我的网络服务** (11认同)
  • 正如@Isuru所说,这是基于http://stackoverflow.com/a/25623647/1187415,现已更新为Swift 2. (11认同)
  • 感谢您的快速反应(没有双关语).麻省理工学院或阿帕奇将是理想的 - 谢谢! (6认同)
  • 完成.把它改成麻省理工学院. (4认同)
  • @János:现在可以使用Swift 2设置通知回调,请参阅更新的答案http://stackoverflow.com/a/27142665/1187415. (2认同)
  • @Isuru当您连接到4G网络时,这不起作用.它返回false (2认同)

Dmi*_*try 16

我给你更好的方法......

您必须使用此代码创建一个类

 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
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用以下代码检查项目中任何位置的互联网连接:

if Reachability.isConnectedToNetwork() == true {
     println("Internet connection OK")
} else {
     println("Internet connection FAILED")
}
Run Code Online (Sandbox Code Playgroud)

很容易!

*这种方式是基于Vikram Pote的答案!

  • 请注意,您应该**不要**使用此方法而不是上面使用的方法.在需要持续连接的应用程序中,像此方法一样的响应检查将导致应用程序在您的Internet连接较差的情况下挂起(即在Edge/GPRS上).请不要使用此解决方案!! (14认同)
  • 糟糕的方式1)需要额外点击服务器evry时间2)http://google.com/也可以关闭 (7认同)
  • 1.是的,这种方式每次都需要额外点击服务器,但它可以100%保证互联网可用......有时候设备连接到wifi网络但不提供互联网接入!在这种情况下,这种方式决定了无法访问互联网......其他方式 - 不!2.您可以使用自己的服务器而不是google.com ...这本来就是...... (2认同)
  • 请gokhanakkurt建议另一种解决方案,以确保Internet可以100%正常工作 (2认同)

iKK*_*iKK 14

适用于Swift 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
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是区分网络类型的整个Reachability-Class:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

由于不推荐使用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
    }
}
Run Code Online (Sandbox Code Playgroud)


Gil*_*man 6

SWIFT 3: 检查wifi互联网连接:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

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

  • 对于您的用例,`public func isConnectedToNetwork() {...}` 应该更改为 `class func isConnectedToNetwork{...}`。 (2认同)