当我试着在我的iPhone上检查网络连接时,我得到了一堆错误。有人能帮我解决这个问题吗?

代码:

import Foundation
import SystemConfiguration

public class Reachability {

class func isConnectedToNetwork() -> Bool {

    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)

    let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
        SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
    }

    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) ? true : false
}

}

代码的错误:

如果它是不可读的,错误1说:

'Int'不能转换为'SCNetworkReachabilityFlags'

错误2和3:

找不到一个超载的'init'接受提供的参数


当前回答

更新版本的@martin的答案Swift 5+使用组合。它还包括iOS 14的不可用原因检查。

import Combine
import Network

enum NetworkType {
    case wifi
    case cellular
    case loopBack
    case wired
    case other
}

final class ReachabilityService: ObservableObject {

    @Published var reachabilityInfos: NWPath?
    @Published var isNetworkAvailable: Bool?
    @Published var typeOfCurrentConnection: NetworkType?

    private let monitor = NWPathMonitor()
    private let backgroundQueue = DispatchQueue.global(qos: .background)

    init() {
        setUp()
    }

    init(with interFaceType: NWInterface.InterfaceType) {
        setUp()
    }

    deinit {
        monitor.cancel()
    }
}

private extension ReachabilityService {

    func setUp() {

        monitor.pathUpdateHandler = { [weak self] path in
            self?.reachabilityInfos = path
            switch path.status {
            case .satisfied:
                print("ReachabilityService: satisfied")
                self?.isNetworkAvailable = true
                break
            case .unsatisfied:
                print("ReachabilityService: unsatisfied")

                if #available(iOS 14.2, *) {
                    switch path.unsatisfiedReason {

                    case .notAvailable:
                        print("ReachabilityService: unsatisfiedReason: notAvailable")
                        break
                    case .cellularDenied:
                        print("ReachabilityService: unsatisfiedReason: cellularDenied")
                        break
                    case .wifiDenied:
                        print("ReachabilityService: unsatisfiedReason: wifiDenied")
                        break
                    case .localNetworkDenied:
                        print("ReachabilityService: unsatisfiedReason: localNetworkDenied")
                        break
                    @unknown default:
                        print("ReachabilityService: unsatisfiedReason: default")
                    }
                } else {
                    // Fallback on earlier versions
                }

                self?.isNetworkAvailable = false
                break
            case .requiresConnection:
                print("ReachabilityService: requiresConnection")
                self?.isNetworkAvailable = false
                break
            @unknown default:
                print("ReachabilityService: default")
                self?.isNetworkAvailable = false
            }
            if path.usesInterfaceType(.wifi) {
                self?.typeOfCurrentConnection = .wifi
            } else if path.usesInterfaceType(.cellular) {
                self?.typeOfCurrentConnection = .cellular
            } else if path.usesInterfaceType(.loopback) {
                self?.typeOfCurrentConnection = .loopBack
            } else if path.usesInterfaceType(.wiredEthernet) {
                self?.typeOfCurrentConnection = .wired
            } else if path.usesInterfaceType(.other) {
                self?.typeOfCurrentConnection = .other
            }
        }

        monitor.start(queue: backgroundQueue)
    }
}

用法:

在视图模型中:

private let reachability = ReachabilityService()

init() {
    reachability.$isNetworkAvailable.sink { [weak self] isConnected in
        self?.isConnected = isConnected ?? false
    }.store(in: &cancelBag)
}

在你的控制器中:

viewModel.$isConnected.sink { [weak self] isConnected in
    print("isConnected: \(isConnected)")
    DispatchQueue.main.async {
        //Update your UI in here
    }
}.store(in: &bindings)

其他回答

这里是我的解决方案swift 2.3与库(reach .swift)

进入你的Podfile并添加:

pod 'ReachabilitySwift', '~> 2.4' // swift 2.3

然后进入您的终端:

pod install

然后创建一个新的文件ReachabilityManager并添加下面的代码:

import Foundation
import ReachabilitySwift

enum ReachabilityManagerType {
    case Wifi
    case Cellular
    case None
}

class ReachabilityManager {
    static let sharedInstance = ReachabilityManager()

    private var reachability: Reachability!
    private var reachabilityManagerType: ReachabilityManagerType = .None


    private init() {
        do {
            self.reachability = try Reachability.reachabilityForInternetConnection()
        } catch {
            print("Unable to create Reachability")
            return
        }

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ReachabilityManager.reachabilityChanged(_:)),name: ReachabilityChangedNotification,object: self.reachability)
        do{
            try self.reachability.startNotifier()
        }catch{
            print("could not start reachability notifier")
        }
    }

    @objc private func reachabilityChanged(note: NSNotification) {

        let reachability = note.object as! Reachability

        if reachability.isReachable() {
            if reachability.isReachableViaWiFi() {
                self.reachabilityManagerType = .Wifi
            } else {
                self.reachabilityManagerType = .Cellular
            }
        } else {
            self.reachabilityManagerType = .None
        }
    }
}

extension ReachabilityManager {

    func isConnectedToNetwork() -> Bool {
        return reachabilityManagerType != .None
    }

}

如何使用:

进入你的AppDelegate.swift并添加下面的代码:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
     ReachabilityManager.sharedInstance
}

然后,当你想检查设备是否连接到互联网时,请:

if ReachabilityManager.sharedInstance.isConnectedToNetwork() {
   // Connected
} else {
  // Not connected
}

对于Swift 3, Swift 4(使用蜂窝和Wi-Fi):

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(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 = SCNetworkReachabilityFlags(rawValue: 0)
        if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
            return false
        }

        /* Only Working for WIFI
        let isReachable = flags == .reachable
        let needsConnection = flags == .connectionRequired

        return isReachable && !needsConnection
        */

        // Working for Cellular and WIFI
        let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        let ret = (isReachable && !needsConnection)

        return ret

    }
}

用法:

if Reachability.isConnectedToNetwork(){
    print("Internet Connection Available!")
}else{
    print("Internet Connection not Available!")
}

斯威夫特5

import SystemConfiguration    

protocol Utilities {}
extension NSObject: Utilities {
    enum ReachabilityStatus {
        case notReachable
        case reachableViaWWAN
        case reachableViaWiFi
    }
    
    var currentReachabilityStatus: ReachabilityStatus {
        
        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 .notReachable
        }
        
        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return .notReachable
        }
        
        if flags.contains(.reachable) == false {
            // The target host is not reachable.
            return .notReachable
        }
        else if flags.contains(.isWWAN) == true {
            // WWAN connections are OK if the calling application is using the CFNetwork APIs.
            return .reachableViaWWAN
        }
        else if flags.contains(.connectionRequired) == false {
            // If the target host is reachable and no connection is required then we'll assume that you're on Wi-Fi...
            return .reachableViaWiFi
        }
        else if (flags.contains(.connectionOnDemand) == true || flags.contains(.connectionOnTraffic) == true) && flags.contains(.interventionRequired) == false {
            // The connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs and no [user] intervention is needed
            return .reachableViaWiFi
        }
        else {
            return .notReachable
        }
    }
}

在任何方法中使用下面的条件

if currentReachabilityStatus == .notReachable {
    // Network Unavailable
} else {
    // Network Available
}

在项目中创建一个新的Swift文件,命名为Reachability.swift。将以下代码剪切并粘贴到其中以创建您的类。

import Foundation
import SystemConfiguration

open class Reachability {
    
    class 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)
            }
        }
        
        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)
    }
}

你可以在代码的任何地方调用Reachability,就像

if Reachability.isConnectedToNetwork() {
    print("Network is connected")
} else {
    print("Network is not connected")
}

iOS12 Swift 4和Swift 5

如果你只是想检查连接,你的最低目标是iOS12,那么你可以使用NWPathMonitor

import Network

它需要一些属性的设置。

let internetMonitor = NWPathMonitor()
let internetQueue = DispatchQueue(label: "InternetMonitor")
private var hasConnectionPath = false

我创建了一个函数来启动它。你可以在viewdidload或其他地方做这个。我派了个保镖,你想怎么打就怎么打。

func startInternetTracking() {
    // only fires once
    guard internetMonitor.pathUpdateHandler == nil else {
        return
    }
    internetMonitor.pathUpdateHandler = { update in
        if update.status == .satisfied {
            print("Internet connection on.")
            self.hasConnectionPath = true
        } else {
            print("no internet connection.")
            self.hasConnectionPath = false
        }
    }
    internetMonitor.start(queue: internetQueue)
}

/// will tell you if the device has an Internet connection
/// - Returns: true if there is some kind of connection
func hasInternet() -> Bool {
    return hasConnectionPath
}

现在只需调用helper函数hasInternet()来查看是否有。它实时更新。请参阅Apple文档中的NWPathMonitor。它有更多的功能,如取消(),如果你需要停止跟踪连接,你正在寻找的互联网类型等。 https://developer.apple.com/documentation/network/nwpathmonitor