如何迅速解决此问题。我必须检查网络连接。如果互联网未连接到设备,则必须显示此offlineViewController
。如果已连接,则显示“正常”屏幕。
答案 0 :(得分:0)
import Alamofire
struct Connectivity {
static let sharedInstance = NetworkReachabilityManager()!
static var isConnectedToInternet:Bool {
return self.sharedInstance.isReachable
}
}
用法:
if Connectivity.isConnectedToInternet {
return true
} else {
self.setErrorMessage(message: "No internet connection", view: view)
return false
}
答案 1 :(得分:0)
class NetworkManager {
//shared instance
static let shared = NetworkManager()
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")
let offlineViewController = OfflineViewController()
let currentViewController: UIViewController?
func startNetworkReachabilityObserver() {
reachabilityManager?.listener = { status in
switch status {
case .notReachable:
offlineViewController.dismiss(animated: false, completion: nil)
currentViewController.present(offlineViewController, animated: true, completion: nil)
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
case .reachable(.ethernetOrWiFi):
offlineViewController.dismiss(animated: true, completion: nil)
print("The network is reachable over the WiFi connection")
case .reachable(.wwan):
offlineViewController.dismiss(animated: true, completion: nil)
print("The network is reachable over the WWAN connection")
}
}
// start listening
reachabilityManager?.startListening()
}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// add network reachability observer on app start
NetworkManager.shared.startNetworkReachabilityObserver()
return true
}
}
override func viewDidLoad() {
super.viewDidLoad()
NetworkManager.shared.currentViewController = self
}
答案 2 :(得分:0)
我正在使用此类来控制网络更改-> 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
}
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
}
var status: Network.Status {
return !isConnectedToNetwork ? .unreachable :
isReachableViaWiFi ? .wifi :
isRunningOnDevice ? .wwan : .unreachable
}
var isRunningOnDevice: Bool = {
#if (arch(i386) || arch(x86_64)) && os(iOS)
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, CustomStringConvertible {
case unreachable, wifi, wwan
var description: String { return rawValue }
}
enum Error: Swift.Error {
case failedToSetCallout
case failedToSetDispatchQueue
case failedToCreateWith(String)
case failedToInitializeWith(sockaddr_in)
}
}
然后将此代码添加到 AppDelegate.swift :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
do {
Network.reachability = try Reachability(hostname: "www.google.com")
do {
try Network.reachability?.start()
} catch let error as Network.Error {
print(error)
} catch {
print(error)
}
} catch {
print(error)
}
return true
}
然后将以下代码添加到要控制网络的类中的 viewDidLoad() :
NotificationCenter.default.addObserver(self, selector: #selector(statusManager), name: .flagsChanged, object: Network.reachability)
当网络改变时,您可以使用此功能进行检查。
func statusManager(_ notification: NSNotification) {
guard let status = Network.reachability?.status else { return }
if status == .wifi || status == .wwan {
offlineViewController.dismiss(animated: true, completion: nil)
}
print("Status:", status)
print("HostName:", Network.reachability?.hostname ?? "nil")
print("Reachable:", Network.reachability?.isReachable ?? "nil")
print("Wifi:", Network.reachability?.isReachableViaWiFi ?? "nil")
}
答案 3 :(得分:0)
这里我使用的是 Alamofire 5.2 版
NetworkReachabilityManager 处理程序
import Alamofire
class NetworkReachability{
let sceneDelegate: SceneDelegate = {
let scene = UIApplication.shared.connectedScenes.first
let sd = scene?.delegate as? SceneDelegate
return sd ?? SceneDelegate()
}()
var manager:NetworkReachabilityManager?
init(
manager:NetworkReachabilityManager? = NetworkReachabilityManager()
) {
self.manager = manager
self.managerHandler()
}
private func managerHandler(){
self.manager?.startListening(onUpdatePerforming: { (status) in
switch status{
case .unknown:
self.sceneDelegate.showOfflineViewController()
case .notReachable:
print("Not Reachable")
self.sceneDelegate.showOfflineViewController()
case .reachable(.cellular),.reachable(.ethernetOrWiFi):
print("Reachable")
self.sceneDelegate.hideOfflineViewController()
}
})
}
}
场景委托
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var offlineWindow:UIWindow?
private var networkReachability:NetworkReachability?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
self.networkReachability = NetworkReachability()
}
}
extension SceneDelegate{
func showOfflineViewController(){
guard let offlineWindow = window?.windowScene else { return }
let offlineViewController = OfflineViewController
self.offlineWindow = UIWindow(windowScene: offlineWindow)
self.offlineWindow?.rootViewController = offlineViewController
self.offlineWindow?.makeKeyAndVisible()
}
func hideOfflineViewController(){
UIView.animate(withDuration: 0.3) {
self.offlineWindow?.alpha = 0
} completion: { (_) in
self.offlineWindow?.isHidden = true
self.offlineWindow = nil
}
}
}