当我试着在我的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'接受提供的参数
在以下代码的帮助下,您可以检查网络连接的蜂窝网络以及wifi。
Swift 3.0
import UIKit
import Foundation
import SystemConfiguration
class NetworkConnection: UIViewController {
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)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return false
}
var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == false {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection)
}
class func checkConnection(sender:UIViewController){
if NetworkConnection.isConnectedToNetwork() == true {
print("Connected to the internet")
// Do something
} else {
print("No internet connection")
let alertController = UIAlertController(title: "No Internet Available", message: "", preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default){(result:UIAlertAction) -> Void in
return
}
alertController.addAction(okAction)
sender.present(alertController, animated: true, completion: nil)
// Do something
}
}
}
我使用NSTimer和Alamofire制作了自己的解决方案:
import Alamofire
public class ConnectionHelper: NSObject {
var request: Alamofire.Request?
func isInternetConnected(completionHandler: Bool -> Void) {
NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "requestTimeout", userInfo: nil, repeats: false)
request = Alamofire
.request(
Method.HEAD,
"http://www.testurl.com"
)
.response { response in
if response.3?.code == -999 {
completionHandler(
false
)
} else {
completionHandler(
true
)
}
}
}
func requestTimeout() {
request!.cancel()
}
}
NSTimer被用作超时,并且由于使用Alamofire超时的不可靠结果而被使用。请求应该发送到您认为可靠的URL,例如您自己的服务器或托管您所依赖的服务的服务器。
当计时器过期时,请求将被取消,并使用完成处理程序返回结果。
用法:
ConnectionHelper().isInternetConnected() { internetConnected in
if internetConnected {
// Connected
} else {
// Not connected
}
}
虽然没有直接回答你的问题,但我想提一下苹果公司最近有这样一个谈话:
https://developer.apple.com/videos/play/wwdc2018/714/
大约在9点55分,他谈到了做你正在问的事情:
检查连接
如果连接->做点什么
如果没有连接->执行其他操作(等待?重试?)
然而,这有一些陷阱:
如果在第二步中,它说它有连接,但0.5秒后他就没有了呢?
如果用户在代理的后面呢
最后但并非最不重要的是,如果这里的一些答案不能确定连通性呢?(我敢肯定,如果你快速切换你的连接,去wi-fi,然后关掉它(只是让它变得复杂),它几乎永远不能正确地判断我是否获得了连接)。
视频中说:“没有办法保证未来的行动是否会成功。”
以下是苹果公司的一些最佳实践:
设置waitsForConnectivity为true (https://developer.apple.com/documentation/foundation/urlsessionconfiguration/2908812-waitsforconnectivity)
响应委托方法taskIsWaitingForConnectivity (https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/2908819-urlsession)。这是苹果推荐的检查连接的方法,正如33:25的视频中提到的那样。
根据谈话,不应该有任何理由预先检查你是否有互联网连接,因为在你向服务器发送请求时,它可能并不准确。
我改进了莱科斯的例子。我添加了一些额外的控件来解决双重触发问题,还添加了通知支持来侦听状态更改。
我为防止双重触发问题而添加的控件还显示了设备主要使用哪个连接源来访问互联网。
例如,即使设备同时连接到蜂窝网络和Wi-Fi,“状态”返回为“connectedViaWiFi”,以指示当前的互联网访问是通过Wi-Fi。
import Foundation
import Network
class Reachability {
enum StatusFlag {
case unknow
case noConnection
case connectedViaWiFi
case connectedViaCellular
}
static let connectionStatusHasChangedNotification = NSNotification.Name("Reachability.connectionStatusHasChangedNotification")
static let shared = Reachability()
private var monitorForWifi: NWPathMonitor?
private var monitorForCellular: NWPathMonitor?
private var wifiStatus: NWPath.Status = .requiresConnection
private var cellularStatus: NWPath.Status = .requiresConnection
private var ignoreInitialWiFiStatusUpdate: Bool = true
private var ignoreInitialCelluluarStatusUpdate: Bool = true
private var isReachableOnCellular: Bool { cellularStatus == .satisfied }
private var isReachableOnWiFi: Bool { wifiStatus == .satisfied }
var status: StatusFlag = .unknow {
didSet {
guard status != oldValue else { return }
DispatchQueue.main.async { [weak self] in
NotificationCenter.default.post(name: Self.connectionStatusHasChangedNotification,
object: self?.status)
}
}
}
func startMonitoring() {
monitorForWifi = NWPathMonitor(requiredInterfaceType: .wifi)
monitorForWifi?.pathUpdateHandler = { [weak self] path in
self?.wifiStatus = path.status
self?.ignoreInitialWiFiStatusUpdate = false
self?.updateStatus()
}
monitorForCellular = NWPathMonitor(requiredInterfaceType: .cellular)
monitorForCellular?.pathUpdateHandler = { [weak self] path in
self?.cellularStatus = path.status
self?.ignoreInitialCelluluarStatusUpdate = false
self?.updateStatus()
}
let queue = DispatchQueue.global(qos: .background)
monitorForCellular?.start(queue: queue)
monitorForWifi?.start(queue: queue)
}
func stopMonitoring() {
monitorForWifi?.cancel()
monitorForWifi = nil
monitorForCellular?.cancel()
monitorForCellular = nil
wifiStatus = .requiresConnection
cellularStatus = .requiresConnection
status = .unknow
ignoreInitialWiFiStatusUpdate = true
ignoreInitialCelluluarStatusUpdate = true
}
private func updateStatus() {
if ignoreInitialWiFiStatusUpdate || ignoreInitialCelluluarStatusUpdate {
return
}
if !(isReachableOnCellular && isReachableOnWiFi) {
if isReachableOnCellular && !isReachableOnWiFi {
status = .connectedViaCellular
} else if isReachableOnWiFi && !isReachableOnCellular {
status = .connectedViaWiFi
} else {
status = .noConnection
}
} else {
status = .connectedViaWiFi
}
}
static func isConnectedToNetwork() -> Bool {
return shared.isReachableOnCellular || shared.isReachableOnWiFi
}
}
示例使用
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityChanged(_:)), name: Reachability.connectionStatusHasChangedNotification, object: nil)
Reachability.shared.startMonitoring()
}
@objc func reachabilityChanged(_ sender: Notification) {
guard let statusFlag = sender.object as? Reachability.StatusFlag else { return }
print("TEST -> statusFlag: \(statusFlag)")
}
这里是我的解决方案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 5.5, iOS 12+,没有更多的第三方库。
请检查这个要点https://gist.github.com/dimohamdy/5166ba6c88f6954fa6b23bc9f28cbe12
使用
startNetworkReachabilityObserver()
if Reachability.shared.isConnected {
print("no internet connection")
}
Code
import Network
import Foundation
class Reachability {
static var shared = Reachability()
lazy private var monitor = NWPathMonitor()
var isConnected: Bool {
return monitor.currentPath.status == .satisfied
}
func startNetworkReachabilityObserver() {
monitor.pathUpdateHandler = { path in
if path.status == .satisfied {
NotificationCenter.default.post(name: Notifications.Reachability.connected.name, object: nil)
} else if path.status == .unsatisfied {
NotificationCenter.default.post(name: Notifications.Reachability.notConnected.name, object: nil)
}
}
let queue = DispatchQueue.global(qos: .background)
monitor.start(queue: queue)
}
}