当我试着在我的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'接受提供的参数
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 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()
斯威夫特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
}
There is no real way to do this, even APIs that do this will try to connect to a particular service and tell you if it succeed after previously failing, the best approach is to just try to connect to your service and handle the error appropriately, if you want some service that will notify you when you become connected, all that will happens is that it periodically calls to a fixed service until it gets a response and then let you know that it succeed, what if the problem is not the internet itself but the specific service you are trying to connect to.
最好的方法是在你的连接方法中设计处理这个问题的方法,你可以在给定的时间内触发重试,这取决于你的错误,也许是失败的数量,你可以返回一个错误,你可以用它来显示一个错误消息,给用户一个重试的可能性,也许是尝试几次,然后返回和错误的组合。
另一个类似的问题是发送你已经发送但还没有得到响应的消息,最好还是写你的应用程序来处理这个,忽略请求,直到它等待的请求返回,如果请求不同,取消等待请求,等等
这些东西可以以非常通用的方式编写,所以它们可以用于应用程序的许多不同方面,甚至不同的项目。
这是我的版本。本质上,它没有带来任何新东西。我把它绑定到UIDevice。
import UIKit
import SystemConfiguration
extension UIDevice {
open class var isConnectedToNetwork: Bool {
get {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
guard
let defaultRouteReachability: SCNetworkReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}),
var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags() as SCNetworkReachabilityFlags?,
SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags)
else { return false }
return flags.contains(.reachable) && !flags.contains(.connectionRequired)
}
}
}
print("Network status availability: " + ( UIDevice.isConnectedToNetwork ? "true" : "false" ))