当我试着在我的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)
这是与接受的答案相同的代码,但我发现在某些情况下使用闭包更有用
import SystemConfiguration
public class Reachability {
class func isConnectedToNetwork(isConnected : (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 {
isConnected(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)
isConnected(ret)
}
}
下面是如何使用它:
Reachability.isConnectedToNetwork { (isConnected) in
if isConnected {
//We have internet connection | get data from server
} else {
//We don't have internet connection | load from database
}
}
对于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!")
}
这里是我的解决方案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
}