检查 Swift 中的互联网连接可用性
Posted
技术标签:
【中文标题】检查 Swift 中的互联网连接可用性【英文标题】:Check for internet connection availability in Swift 【发布时间】:2014-10-13 10:53:14 【问题描述】:有没有办法使用 Swift 检查互联网连接是否可用?
我知道有很多第三方库可以做到这一点,但它们都是用 Objective-C 编写的。我正在寻找 Swift 替代方案。
【问题讨论】:
Swift 的一大优势是它可以很好地与 Objective-C(以及此类库)集成。 确实如此。您在使用现有库之一时遇到什么问题?使用 Swift 的 Objective C 库非常简单,如果你不会用 Swift 编写任何类型的应用程序,那将是极其困难的。 @MattGibson 几乎你可以在 ObjC 中做的所有事情都可以在 Swift 中相对轻松地完成。诚然,在这种情况下会有一些额外的行,但仍远非“极其困难” @ByronCoetsee 我包括使用 AppKit 等库。我的意思是,您需要知道如何与 Objective C 库进行交互才能在 Swift 中编写任何有用的东西。 查看 alamofire 答案 - ***.com/a/46562290/7576100 【参考方案1】:如果你在你的项目中使用 Alamofire,你可以使用这个示例函数:
import Alamofire
class Network
func isConnected(_ complition: @escaping(Bool) -> Void)
let retVal = NetworkReachabilityManager()!.isReachable
complition(retVal)
【讨论】:
【参考方案2】:我找到了所有答案中最好的,并且每次都会继续检查 Internet 连接状态。
要开始,首先为网络框架添加一个导入:
import Network
接下来,创建一个 NWPathMonitor 实例
let monitor = NWPathMonitor()
要试试这个,
monitor.pathUpdateHandler = path in
if path.status == .satisfied
print("We're connected!")
else
print("No connection.")
print(path.isExpensive)
请记住,每次连接状态更改时都会调用该闭包。
let queue = DispatchQueue(label: "Monitor")
monitor.start(queue: queue)
这里我是如何在我的视图控制器中使用它的,
class testViewController: UIViewController
@IBOutlet weak var status: UILabel!
let monitor = NWPathMonitor()
override func viewDidLoad()
super.viewDidLoad()
let queue = DispatchQueue(label: "Monitor")
monitor.start(queue: queue)
_ = NWPathMonitor(requiredInterfaceType: .cellular)
monitor.pathUpdateHandler = path in
if path.status == .satisfied
print("We're connected!")
DispatchQueue.main.async
self.status.text = "We're connected!"
else
print("No connection.")
DispatchQueue.main.async
self.status.text = "No connection."
【讨论】:
请感谢 Hacking With Swift 这个答案! hackingwithswift.com/example-code/networking/…【参考方案3】:斯威夫特 4
if isInternetAvailable()
print("if called Internet Connectivity success \(isInternetAvailable())");
else
print("else called Internet Connectivity success \(isInternetAvailable())");
func isInternetAvailable() -> 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.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
// print(isReachable && !needsConnection)
return (isReachable && !needsConnection)
【讨论】:
【参考方案4】:对于 Swift 5:
import Network
let monitor = NWPathMonitor()
func checkInterwebs() -> Bool
var status = false
monitor.pathUpdateHandler = path in
if path.status == .satisfied
status = true // online
return status
【讨论】:
好像这行不通,因为你没有这样做monitor.start(queue: someQueue)
【参考方案5】:
正如 cmets 中提到的,虽然它可以在 Swift 中使用 Objective-C 库,但我想要一个更纯粹的 Swift 解决方案。现有的 Apple Reachability 类和其他第三方库对于我来说似乎太复杂而无法转换为 Swift。我在 Google 上搜索了更多内容,发现了这个 article,它显示了一种检查网络可用性的简单方法。我开始把它翻译成 Swift。我遇到了很多snags,但感谢来自 *** 的Martin R,我设法解决了这些问题,并最终在 Swift 中找到了一个可行的解决方案。这是代码。
import Foundation
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(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(&zeroAddress)
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)).takeRetainedValue()
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
对于 Swift > 3.0
public class Reachability
public func isConnectedToNetwork() -> Bool
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 false
var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags)
return false
if flags.isEmpty
return false
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
这适用于 3G 和 WiFi 连接。我还通过一个工作示例将其上传到我的GitHub。
【讨论】:
感谢您的快速响应(不是双关语)。 MIT 或 Apache 将是理想的 - 谢谢! 完成。改为麻省理工学院。 我发现了另一个问题,如果 3G 已打开但我没有更多数据容量,那么isConnectedToNetwork
返回 true,但我无法调用我的网络服务
正如@Isuru 所说,这是基于***.com/a/25623647/1187415,现在已针对Swift 2 进行了更新。
@János:现在可以使用 Swift 2 设置通知回调,请参阅更新的答案 ***.com/a/27142665/1187415。【参考方案6】:
SWIFT 3: 检查 wifi 和 internet 连接:
import Foundation
import SystemConfiguration
public class Reachability
public func isConnectedToNetwork() -> Bool
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 false
var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags)
return false
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
用法:
if Reachability.isConnectedToNetwork() == true
print("Connected to the internet")
// Do something
else
print("No internet connection")
// Do something
【讨论】:
public func isConnectedToNetwork() ...
应更改为 class func isConnectedToNetwork...
以供您使用。【参考方案7】:
SWIFT 3:检查 3G 和 Wi-Fi 连接
DispatchQueue.main.async
let url = URL(string: "https://www.google.com")!
let request = URLRequest(url: url)
let task = URLSession.shared.dataTask(with: request) data, response, error in
if error != nil
// do something here...
print("Internet Connection not Available!")
else if let httpResponse = response as? HTTPURLResponse
if httpResponse.statusCode == 200
// do something here...
print("Internet Connection OK")
print("statusCode: \(httpResponse.statusCode)")
task.resume()
【讨论】:
这不是首选方式。如果在将来某个时间点提供的 Web 链接停止响应或关闭,该怎么办。我建议为此使用 Apple SystemConfiguration 框架。请参阅上面的答案。【参考方案8】:适用于 Swift 3.1 (iOS 10.1)
如果您想区分网络类型(即 WiFi 或 WWAN):
你可以使用:
func checkWiFi() -> Bool
let networkStatus = Reachability().connectionStatus()
switch networkStatus
case .Unknown, .Offline:
return false
case .Online(.WWAN):
print("Connected via WWAN")
return true
case .Online(.WiFi):
print("Connected via WiFi")
return true
这是区分网络类型的整个可达性类:
import Foundation
import SystemConfiguration
import UIKit
import SystemConfiguration.CaptiveNetwork
public let ReachabilityStatusChangedNotification = "ReachabilityStatusChangedNotification"
public enum ReachabilityType: CustomStringConvertible
case WWAN
case WiFi
public var description: String
switch self
case .WWAN: return "WWAN"
case .WiFi: return "WiFi"
public enum ReachabilityStatus: CustomStringConvertible
case Offline
case Online(ReachabilityType)
case Unknown
public var description: String
switch self
case .Offline: return "Offline"
case .Online(let type): return "Online (\(type))"
case .Unknown: return "Unknown"
public class Reachability
func connectionStatus() -> ReachabilityStatus
var zeroAddress = sockaddr_in()
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) zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
) else
return .Unknown
var flags : SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags)
return .Unknown
return ReachabilityStatus(reachabilityFlags: flags)
func monitorReachabilityChanges()
let host = "google.com"
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
let reachability = SCNetworkReachabilityCreateWithName(nil, host)!
SCNetworkReachabilitySetCallback(reachability, (_, flags, _) in
let status = ReachabilityStatus(reachabilityFlags: flags)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: ReachabilityStatusChangedNotification), object: nil, userInfo: ["Status": status.description]), &context)
SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
extension ReachabilityStatus
public init(reachabilityFlags flags: SCNetworkReachabilityFlags)
let connectionRequired = flags.contains(.connectionRequired)
let isReachable = flags.contains(.reachable)
let isWWAN = flags.contains(.isWWAN)
if !connectionRequired && isReachable
if isWWAN
self = .Online(.WWAN)
else
self = .Online(.WiFi)
else
self = .Offline
【讨论】:
自 2016 年 12 月 3 日起运行良好,ios 10 和 swift 3.1,谢谢! 您好,如果我们想区分 Wifi/3G/Mobile-Data/4G 连接,我们如何识别。【参考方案9】:由于不推荐使用 sendSynchronousRequest,我尝试了这个,但在响应完成之前调用了“返回状态”。
这个答案很有效,Check for internet connection with Swift
这就是我尝试过的:
import Foundation
public class Reachability
class func isConnectedToNetwork()->Bool
var Status:Bool = false
let url = NSURL(string: "http://google.com/")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "HEAD"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
request.timeoutInterval = 10.0
let session = NSURLSession.sharedSession()
session.dataTaskWithRequest(request, completionHandler: (data, response, error) in
print("data \(data)")
print("response \(response)")
print("error \(error)")
if let httpResponse = response as? NSHTTPURLResponse
print("httpResponse.statusCode \(httpResponse.statusCode)")
if httpResponse.statusCode == 200
Status = true
).resume()
return Status
【讨论】:
我喜欢并使用了您的解决方案。但我添加了一个与这个答案相结合的:***.com/a/34591379 aka。我添加了一个信号量。所以我等待任务完成。【参考方案10】:你也可以使用下面的答案。
func checkInternet(flag:Bool, completionHandler:(internet:Bool) -> Void)
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
let url = NSURL(string: "http://www.google.com/")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "HEAD"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
request.timeoutInterval = 10.0
NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.mainQueue(), completionHandler:
(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
let rsp = response as NSHTTPURLResponse?
completionHandler(internet:rsp?.statusCode == 200)
)
func yourMethod()
self.checkInternet(false, completionHandler:
(internet:Bool) -> Void in
if (internet)
// "Internet" mean Google
else
// No "Internet" no Google
)
【讨论】:
谢谢!我从响应中得到自动更正为 NSHTTPURLResponse?以回应为! NSHTTPURL响应?在 Swift 1.2 中。【参考方案11】:我给你更好的方法……
您必须使用此代码创建一个类
import Foundation
public class Reachability
class func isConnectedToNetwork()->Bool
var Status:Bool = false
let url = NSURL(string: "http://google.com/")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "HEAD"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
request.timeoutInterval = 10.0
var response: NSURLResponse?
var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) as NSData?
if let httpResponse = response as? NSHTTPURLResponse
if httpResponse.statusCode == 200
Status = true
return Status
然后您可以使用以下代码检查项目中任何地方的互联网连接:
if Reachability.isConnectedToNetwork() == true
println("Internet connection OK")
else
println("Internet connection FAILED")
非常简单!
*这种方式是基于维克拉姆波特的回答!
【讨论】:
请注意,您应该不使用此方法而不是上面使用的方法。在需要持续连接的应用程序中,像这种方法的响应检查将导致应用程序在您的互联网连接较差的情况下挂起(即在 Edge/GPRS 上)。请不要使用此解决方案! 不好的方式 1) 每次都需要对服务器进行额外的点击 2) google.com 也可以关闭 1.是的,这种方式每次都需要对服务器进行额外的访问,但它可以 100% 保证互联网可用......有时设备连接到 wifi 网络但不提供互联网访问!在这种情况下,这种方式决定了无法访问互联网......其他方式 - 不! 2.你可以使用自己的服务器代替google.com ...这本来是... 糟糕的解决方案,连接杀手。 gokhanakkurt,请提出另一种解决方案,以确保互联网以 100% 运行以上是关于检查 Swift 中的互联网连接可用性的主要内容,如果未能解决你的问题,请参考以下文章