当我试着在我的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'接受提供的参数
Swift 5解决方案:
下载ashleymills的Reachability类
https://github.com/ashleymills/Reachability.swift。
将Reachability类添加到项目中。
将以下代码放入维护连接状态的类中
class ConnectionManager {
static let shared = ConnectionManager()
private init () {}
func hasConnectivity() -> Bool {
do {
let reachability: Reachability = try Reachability()
let networkStatus = reachability.connection
switch networkStatus {
case .unavailable:
return false
case .wifi, .cellular:
return true
}
}
catch {
return false
}
}
}
像下面这样使用它:
ConnectionManager.shared.hasConnectivity()
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
这里是我的解决方案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!")
}
这些答案中有许多已经不再适用。
原因是使用vpn(因为冠状病毒,我们现在通过vpn而不是公司的wifi进行测试)
使用苹果的网络框架,并基于这里的代码https://medium.com/@udaykiran.munaga/swift-check-for-internet-connectivity-14e355fa10c5,我能够分别检测到wifi和蜂窝网络。由于使用vpn,路径通常保持满意,因此isConnectedToNetwork()总是返回true。
下面的代码使用了apple Network框架,但重新编写,以便在现有代码中仍然使用Reachability.isConnectedToNetwork()。
import Network
class Reachability {
static let shared = Reachability()
let monitorForWifi = NWPathMonitor(requiredInterfaceType: .wifi)
let monitorForCellular = NWPathMonitor(requiredInterfaceType: .cellular)
private var wifiStatus: NWPath.Status = .requiresConnection
private var cellularStatus: NWPath.Status = .requiresConnection
var isReachable: Bool { wifiStatus == .satisfied || isReachableOnCellular }
var isReachableOnCellular: Bool { cellularStatus == .satisfied }
func startMonitoring() {
monitorForWifi.pathUpdateHandler = { [weak self] path in
self?.wifiStatus = path.status
if path.status == .satisfied {
DLog.message("Wifi is connected!")
// post connected notification
} else {
DLog.message("No wifi connection.")
// post disconnected notification
}
}
monitorForCellular.pathUpdateHandler = { [weak self] path in
self?.cellularStatus = path.status
if path.status == .satisfied {
DLog.message("Cellular connection is connected!")
// post connected notification
} else {
DLog.message("No cellular connection.")
// post disconnected notification
}
}
let queue = DispatchQueue(label: "NetworkMonitor")
monitorForCellular.start(queue: queue)
monitorForWifi.start(queue: queue)
}
func stopMonitoring() {
monitorForWifi.cancel()
monitorForCellular.cancel()
}
class func isConnectedToNetwork() -> Bool {
return shared.isReachable
}
}
然后在你的Appdelegate中didFinishLaunchingWithOptions: start monitoring。
Reachability.shared.startMonitoring()