当我尝试在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’的重载
为了解决注释中提到的4G问题,我已使用@AshleyMills可达性实现作为参考并重写了Swift 3.1的Reachability:
更新: Xcode 10.1•Swift 4或更高版本
Reachability.swift文件
import Foundation
import SystemConfiguration
class Reachability {
var hostname: String?
var isRunning = false
var isReachableOnWWAN: Bool
var reachability: SCNetworkReachability?
var reachabilityFlags = SCNetworkReachabilityFlags()
let reachabilitySerialQueue = DispatchQueue(label: "ReachabilityQueue")
init(hostname: String) throws {
guard let reachability = SCNetworkReachabilityCreateWithName(nil, hostname) else {
throw Network.Error.failedToCreateWith(hostname)
}
self.reachability = reachability
self.hostname = hostname
isReachableOnWWAN = true
try start()
}
init() throws {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let reachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
throw Network.Error.failedToInitializeWith(zeroAddress)
}
self.reachability = reachability
isReachableOnWWAN = true
try start()
}
var status: Network.Status {
return !isConnectedToNetwork ? .unreachable :
isReachableViaWiFi ? .wifi :
isRunningOnDevice ? .wwan : .unreachable
}
var isRunningOnDevice: Bool = {
#if targetEnvironment(simulator)
return false
#else
return true
#endif
}()
deinit { stop() }
}
extension Reachability {
func start() throws {
guard let reachability = reachability, !isRunning else { return }
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
context.info = Unmanaged<Reachability>.passUnretained(self).toOpaque()
guard SCNetworkReachabilitySetCallback(reachability, callout, &context) else { stop()
throw Network.Error.failedToSetCallout
}
guard SCNetworkReachabilitySetDispatchQueue(reachability, reachabilitySerialQueue) else { stop()
throw Network.Error.failedToSetDispatchQueue
}
reachabilitySerialQueue.async { self.flagsChanged() }
isRunning = true
}
func stop() {
defer { isRunning = false }
guard let reachability = reachability else { return }
SCNetworkReachabilitySetCallback(reachability, nil, nil)
SCNetworkReachabilitySetDispatchQueue(reachability, nil)
self.reachability = nil
}
var isConnectedToNetwork: Bool {
return isReachable &&
!isConnectionRequiredAndTransientConnection &&
!(isRunningOnDevice && isWWAN && !isReachableOnWWAN)
}
var isReachableViaWiFi: Bool {
return isReachable && isRunningOnDevice && !isWWAN
}
/// Flags that indicate the reachability of a network node name or address, including whether a connection is required, and whether some user intervention might be required when establishing a connection.
var flags: SCNetworkReachabilityFlags? {
guard let reachability = reachability else { return nil }
var flags = SCNetworkReachabilityFlags()
return withUnsafeMutablePointer(to: &flags) {
SCNetworkReachabilityGetFlags(reachability, UnsafeMutablePointer($0))
} ? flags : nil
}
/// compares the current flags with the previous flags and if changed posts a flagsChanged notification
func flagsChanged() {
guard let flags = flags, flags != reachabilityFlags else { return }
reachabilityFlags = flags
NotificationCenter.default.post(name: .flagsChanged, object: self)
}
/// The specified node name or address can be reached via a transient connection, such as PPP.
var transientConnection: Bool { return flags?.contains(.transientConnection) == true }
/// The specified node name or address can be reached using the current network configuration.
var isReachable: Bool { return flags?.contains(.reachable) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set, the kSCNetworkReachabilityFlagsConnectionOnTraffic flag, kSCNetworkReachabilityFlagsConnectionOnDemand flag, or kSCNetworkReachabilityFlagsIsWWAN flag is also typically set to indicate the type of connection required. If the user must manually make the connection, the kSCNetworkReachabilityFlagsInterventionRequired flag is also set.
var connectionRequired: Bool { return flags?.contains(.connectionRequired) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. Any traffic directed to the specified name or address will initiate the connection.
var connectionOnTraffic: Bool { return flags?.contains(.connectionOnTraffic) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established.
var interventionRequired: Bool { return flags?.contains(.interventionRequired) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. The connection will be established "On Demand" by the CFSocketStream programming interface (see CFStream Socket Additions for information on this). Other functions will not establish the connection.
var connectionOnDemand: Bool { return flags?.contains(.connectionOnDemand) == true }
/// The specified node name or address is one that is associated with a network interface on the current system.
var isLocalAddress: Bool { return flags?.contains(.isLocalAddress) == true }
/// Network traffic to the specified node name or address will not go through a gateway, but is routed directly to one of the interfaces in the system.
var isDirect: Bool { return flags?.contains(.isDirect) == true }
/// The specified node name or address can be reached via a cellular connection, such as EDGE or GPRS.
var isWWAN: Bool { return flags?.contains(.isWWAN) == true }
/// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set
/// The specified node name or address can be reached via a transient connection, such as PPP.
var isConnectionRequiredAndTransientConnection: Bool {
return (flags?.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]) == true
}
}
func callout(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
guard let info = info else { return }
DispatchQueue.main.async {
Unmanaged<Reachability>
.fromOpaque(info)
.takeUnretainedValue()
.flagsChanged()
}
}
extension Notification.Name {
static let flagsChanged = Notification.Name("FlagsChanged")
}
struct Network {
static var reachability: Reachability!
enum Status: String {
case unreachable, wifi, wwan
}
enum Error: Swift.Error {
case failedToSetCallout
case failedToSetDispatchQueue
case failedToCreateWith(String)
case failedToInitializeWith(sockaddr_in)
}
}
用法
在您的AppDelegate.swift didFinishLaunchingWithOptions方法中对其进行初始化,并处理可能发生的任何错误:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
do {
try Network.reachability = Reachability(hostname: "www.google.com")
}
catch {
switch error as? Network.Error {
case let .failedToCreateWith(hostname)?:
print("Network error:\nFailed to create reachability object With host named:", hostname)
case let .failedToInitializeWith(address)?:
print("Network error:\nFailed to initialize reachability object With address:", address)
case .failedToSetCallout?:
print("Network error:\nFailed to set callout")
case .failedToSetDispatchQueue?:
print("Network error:\nFailed to set DispatchQueue")
case .none:
print(error)
}
}
return true
}
}
和一个视图控制器示例:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default
.addObserver(self,
selector: #selector(statusManager),
name: .flagsChanged,
object: nil)
updateUserInterface()
}
func updateUserInterface() {
switch Network.reachability.status {
case .unreachable:
view.backgroundColor = .red
case .wwan:
view.backgroundColor = .yellow
case .wifi:
view.backgroundColor = .green
}
print("Reachability Summary")
print("Status:", Network.reachability.status)
print("HostName:", Network.reachability.hostname ?? "nil")
print("Reachable:", Network.reachability.isReachable)
print("Wifi:", Network.reachability.isReachableViaWiFi)
}
@objc func statusManager(_ notification: Notification) {
updateUserInterface()
}
}
样例项目
问题内容: 是否可以使用Swift检查互联网连接是否可用? 我知道有很多第三方库可以执行此操作,但是它们都是用Objective-C编写的。我正在寻找Swift的替代方案。 问题答案: 如评论中所述,尽管可以在Swift中使用Objective-C库,但我想要一个更纯粹的Swift解决方案。现有的AppleReachability类和其他第三方库对于我来说转换为Swift似乎太复杂了。我用Goog
问题内容: 我想看看是否有人在使用Java时有一种简单的方法来检测是否存在Internet连接。当前的应用程序在Windows的WinInit DLL中使用了“InternetGetConnectedState”方法,但是我的应用程序需要跨平台才能进行Mac操作,并且这种方法将无法使用。我完全不知道JNI可以在Java中使用DLL,它很快变得令人沮丧。 我唯一想到的方法是尝试打开与网站的URL连接
你好,我有一个应用程序,有两个活动:主页面和详细页面。 当有互联网连接时,用户可以从主页面导航到详细信息页面。当没有网络连接时,他不能这样做。 问题是:当我进入详细信息页面并关闭wifi时,我想完成此活动,我如何实现此功能?我在主要活动类中检查过类似这样的内容: 当我启动有互联网或没有互联网的应用程序时,它都可以正常工作,但是当我在运行时关闭wifi时,它不起作用。 无论如何,谢谢你!
我需要检查的设备是否有互联网连接,我搜索一些例子,但当我复制和粘贴的代码,我总是得到错误或不推荐的函数。我也不明白我必须把检查连接的方法放在哪里,因为我需要检查viewModel中的internet连接来发出一些请求,而我找到的所有方法都在参数中有上下文,而我无法在viewModel中获得上下文。 我尝试了这段代码,但我不明白我必须把它放在哪里,我得到 有人能给我解释一下怎么开这张支票吗?
我试着从这个答案(被接受的答案)。我可以使用“PING”方法,但用户界面变黑了,因为它说它会阻止用户界面线程。它看起来不太好,令人不安,所以我尝试使用第二种方法“连接到互联网上的套接字”,但我不知道如何使用Kotlin中的类。 这是android studio将Java转换为kotlin的结果 但是我不知道如何使用它。我试过这样做: 它不起作用,导致了一个错误。它说我必须通过“消费者”。 我的问题
问题内容: 是否有Apple框架捆绑包来检测是否存在互联网连接?当前,当我的应用程序尝试在没有互联网连接的情况下对用户的位置进行地理位置定位时会崩溃。 我对Swift和ios编程有些陌生-抱歉。 问题答案: 这不是一个完善的网络检查库,但是我发现了这种简单的方法来检查网络可用性。我设法将其翻译为Swift,并在这里完成了最终代码。 它适用于3G和WiFi连接。我还通过一个工作示例将其上传到了我的G