0001 // NetworkReachabilityManager.swift 0002 // 0003 // Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/) 0004 // 0005 // Permission is hereby granted, free of charge, to any person obtaining a copy 0006 // of this software and associated documentation files (the "Software"), to deal 0007 // in the Software without restriction, including without limitation the rights 0008 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0009 // copies of the Software, and to permit persons to whom the Software is 0010 // furnished to do so, subject to the following conditions: 0011 // 0012 // The above copyright notice and this permission notice shall be included in 0013 // all copies or substantial portions of the Software. 0014 // 0015 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0016 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0017 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0018 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 0019 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 0020 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 0021 // THE SOFTWARE. 0022 0023 #if !os(watchOS) 0024 0025 import Foundation 0026 import SystemConfiguration 0027 0028 /** 0029 The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and 0030 WiFi network interfaces. 0031 0032 Reachability can be used to determine background information about why a network operation failed, or to retry 0033 network requests when a connection is established. It should not be used to prevent a user from initiating a network 0034 request, as it's possible that an initial request may be required to establish reachability. 0035 */ 0036 public class NetworkReachabilityManager{ 0037 /** 0038 Defines the various states of network reachability. 0039 0040 - Unknown: It is unknown whether the network is reachable. 0041 - NotReachable: The network is not reachable. 0042 - ReachableOnWWAN: The network is reachable over the WWAN connection. 0043 - ReachableOnWiFi: The network is reachable over the WiFi connection. 0044 */ 0045 public enum NetworkReachabilityStatus
NetworkReachabilityManager.swift:156 let reachability = Unmanaged<NetworkReachabilityManager>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()NetworkReachabilityManager.swift:212 extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}NetworkReachabilityManager.swift:223 lhs: NetworkReachabilityManager.NetworkReachabilityStatus,NetworkReachabilityManager.swift:224 rhs: NetworkReachabilityManager.NetworkReachabilityStatus){ 0046 case Unknown
NetworkReachabilityManager.swift:64 public typealias Listener = NetworkReachabilityStatus -> VoidNetworkReachabilityManager.swift:78 public var networkReachabilityStatus: NetworkReachabilityStatus {NetworkReachabilityManager.swift:191 func networkReachabilityStatusForFlags(flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus {NetworkReachabilityManager.swift:194 var networkStatus: NetworkReachabilityStatus = .NotReachableNetworkReachabilityManager.swift:212 extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}NetworkReachabilityManager.swift:223 lhs: NetworkReachabilityManager.NetworkReachabilityStatus,NetworkReachabilityManager.swift:224 rhs: NetworkReachabilityManager.NetworkReachabilityStatus)0047 case NotReachable
NetworkReachabilityManager.swift:79 guard let flags = self.flags else { return .Unknown }NetworkReachabilityManager.swift:228 case (.Unknown, .Unknown):NetworkReachabilityManager.swift:228 case (.Unknown, .Unknown):0048 case Reachable
NetworkReachabilityManager.swift:192 guard flags.contains(.Reachable) else { return .NotReachable }NetworkReachabilityManager.swift:194 var networkStatus: NetworkReachabilityStatus = .NotReachableNetworkReachabilityManager.swift:230 case (.NotReachable, .NotReachable):NetworkReachabilityManager.swift:230 case (.NotReachable, .NotReachable):(ConnectionType) 0049 } 0050 0051 /** 0052 Defines the various connection types detected by reachability flags. 0053 0054 - EthernetOrWiFi: The connection type is either over Ethernet or WiFi. 0055 - WWAN: The connection type is a WWAN connection. 0056 */ 0057 public enum ConnectionType
NetworkReachabilityManager.swift:72 public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .Reachable(.WWAN) }NetworkReachabilityManager.swift:75 public var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .Reachable(.EthernetOrWiFi) }NetworkReachabilityManager.swift:196 if !flags.contains(.ConnectionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }NetworkReachabilityManager.swift:199 if !flags.contains(.InterventionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }NetworkReachabilityManager.swift:232 case let (.Reachable(lhsConnectionType), .Reachable(rhsConnectionType)):NetworkReachabilityManager.swift:232 case let (.Reachable(lhsConnectionType), .Reachable(rhsConnectionType)):{ 0058 case EthernetOrWiFi
NetworkReachabilityManager.swift:48 case Reachable(ConnectionType)0059 case WWAN
NetworkReachabilityManager.swift:75 public var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .Reachable(.EthernetOrWiFi) }NetworkReachabilityManager.swift:196 if !flags.contains(.ConnectionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }NetworkReachabilityManager.swift:199 if !flags.contains(.InterventionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }0060 } 0061 0062 /// A closure executed when the network reachability status changes. The closure takes a single argument: the 0063 /// network reachability status. 0064 public typealias Listener
NetworkReachabilityManager.swift:72 public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .Reachable(.WWAN) }= NetworkReachabilityStatus -> Void 0065 0066 // MARK: - Properties 0067 0068 /// Whether the network is currently reachable. 0069 public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi } 0070 0071 /// Whether the network is currently reachable over the WWAN interface. 0072 public var isReachableOnWWAN
NetworkReachabilityManager.swift:87 public var listener: Listener?: Bool { return networkReachabilityStatus == .Reachable(.WWAN) } 0073 0074 /// Whether the network is currently reachable over Ethernet or WiFi interface. 0075 public var isReachableOnEthernetOrWiFi
NetworkReachabilityManager.swift:69 public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }: Bool { return networkReachabilityStatus == .Reachable(.EthernetOrWiFi) } 0076 0077 /// The current network reachability status. 0078 public var networkReachabilityStatus
NetworkReachabilityManager.swift:69 public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }: NetworkReachabilityStatus { 0079 guard let flags = self.flags else { return .Unknown } 0080 return networkReachabilityStatusForFlags(flags) 0081 } 0082 0083 /// The dispatch queue to execute the `listener` closure on. 0084 public var listenerQueue
NetworkReachabilityManager.swift:72 public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .Reachable(.WWAN) }NetworkReachabilityManager.swift:75 public var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .Reachable(.EthernetOrWiFi) }: dispatch_queue_t = dispatch_get_main_queue() 0085 0086 /// A closure executed when the network reachability status changes. 0087 public var listener
NetworkReachabilityManager.swift:162 let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue)NetworkReachabilityManager.swift:164 dispatch_async(listenerQueue) {: Listener? 0088 0089 private var flags
NetworkReachabilityManager.swift:186 listener?(networkReachabilityStatusForFlags(flags)): SCNetworkReachabilityFlags? { 0090 var flags = SCNetworkReachabilityFlags() 0091 0092 if SCNetworkReachabilityGetFlags(reachability, &flags) { 0093 return flags 0094 } 0095 0096 return nil 0097 } 0098 0099 private let reachability
NetworkReachabilityManager.swift:79 guard let flags = self.flags else { return .Unknown }NetworkReachabilityManager.swift:166 self.notifyListener(self.flags ?? SCNetworkReachabilityFlags()): SCNetworkReachability 0100 private var previousFlags
NetworkReachabilityManager.swift:92 if SCNetworkReachabilityGetFlags(reachability, &flags) {NetworkReachabilityManager.swift:134 self.reachability = reachabilityNetworkReachabilityManager.swift:154 reachability,NetworkReachabilityManager.swift:162 let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue)NetworkReachabilityManager.swift:176 SCNetworkReachabilitySetCallback(reachability, nil, nil)NetworkReachabilityManager.swift:177 SCNetworkReachabilitySetDispatchQueue(reachability, nil): SCNetworkReachabilityFlags 0101 0102 // MARK: - Initialization 0103 0104 /** 0105 Creates a `NetworkReachabilityManager` instance with the specified host. 0106 0107 - parameter host: The host used to evaluate network reachability. 0108 0109 - returns: The new `NetworkReachabilityManager` instance. 0110 */ 0111 public convenience init?(host: String) { 0112 guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil } 0113 self.init(reachability: reachability) 0114 } 0115 0116 /** 0117 Creates a `NetworkReachabilityManager` instance with the default socket address (`sockaddr_in6`). 0118 0119 - returns: The new `NetworkReachabilityManager` instance. 0120 */ 0121 public convenience init?() { 0122 var address = sockaddr_in6() 0123 address.sin6_len = UInt8(sizeofValue(address)) 0124 address.sin6_family = sa_family_t(AF_INET6) 0125 0126 guard let reachability = withUnsafePointer(&address, { 0127 SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) 0128 }) else { return nil } 0129 0130 self.init(reachability: reachability) 0131 } 0132 0133 private init
NetworkReachabilityManager.swift:135 self.previousFlags = SCNetworkReachabilityFlags()NetworkReachabilityManager.swift:165 self.previousFlags = SCNetworkReachabilityFlags()NetworkReachabilityManager.swift:183 guard previousFlags != flags else { return }NetworkReachabilityManager.swift:184 previousFlags = flags(reachability: SCNetworkReachability) { 0134 self.reachability = reachability 0135 self.previousFlags = SCNetworkReachabilityFlags() 0136 } 0137 0138 deinit { 0139 stopListening() 0140 } 0141 0142 // MARK: - Listening 0143 0144 /** 0145 Starts listening for changes in network reachability status. 0146 0147 - returns: `true` if listening was started successfully, `false` otherwise. 0148 */ 0149 public func startListening() -> Bool { 0150 var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) 0151 context.info = UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque()) 0152 0153 let callbackEnabled = SCNetworkReachabilitySetCallback( 0154 reachability, 0155 { (_, flags, info) in 0156 let reachability = Unmanaged<NetworkReachabilityManager>.fromOpaque(COpaquePointer(info)).takeUnretainedValue() 0157 reachability.notifyListener(flags) 0158 }, 0159 &context 0160 ) 0161 0162 let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue) 0163 0164 dispatch_async(listenerQueue) { 0165 self.previousFlags = SCNetworkReachabilityFlags() 0166 self.notifyListener(self.flags ?? SCNetworkReachabilityFlags()) 0167 } 0168 0169 return callbackEnabled && queueEnabled 0170 } 0171 0172 /** 0173 Stops listening for changes in network reachability status. 0174 */ 0175 public func stopListening
NetworkReachabilityManager.swift:113 self.init(reachability: reachability)NetworkReachabilityManager.swift:130 self.init(reachability: reachability)() { 0176 SCNetworkReachabilitySetCallback(reachability, nil, nil) 0177 SCNetworkReachabilitySetDispatchQueue(reachability, nil) 0178 } 0179 0180 // MARK: - Internal - Listener Notification 0181 0182 func notifyListener
NetworkReachabilityManager.swift:139 stopListening()(flags: SCNetworkReachabilityFlags) { 0183 guard previousFlags != flags else { return } 0184 previousFlags = flags 0185 0186 listener?(networkReachabilityStatusForFlags(flags)) 0187 } 0188 0189 // MARK: - Internal - Network Reachability Status 0190 0191 func networkReachabilityStatusForFlags
NetworkReachabilityManager.swift:157 reachability.notifyListener(flags)NetworkReachabilityManager.swift:166 self.notifyListener(self.flags ?? SCNetworkReachabilityFlags())(flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus { 0192 guard flags.contains(.Reachable) else { return .NotReachable } 0193 0194 var networkStatus: NetworkReachabilityStatus = .NotReachable 0195 0196 if !flags.contains(.ConnectionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) } 0197 0198 if flags.contains(.ConnectionOnDemand) || flags.contains(.ConnectionOnTraffic) { 0199 if !flags.contains(.InterventionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) } 0200 } 0201 0202 #if os(iOS) 0203 if flags.contains(.IsWWAN) { networkStatus = .Reachable(.WWAN) } 0204 #endif 0205 0206 return networkStatus 0207 } 0208 } 0209 0210 // MARK: - 0211 0212 extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {} 0213 0214 /** 0215 Returns whether the two network reachability status values are equal. 0216 0217 - parameter lhs: The left-hand side value to compare. 0218 - parameter rhs: The right-hand side value to compare. 0219 0220 - returns: `true` if the two values are equal, `false` otherwise. 0221 */ 0222 public func ==( 0223 lhs: NetworkReachabilityManager.NetworkReachabilityStatus, 0224 rhs: NetworkReachabilityManager.NetworkReachabilityStatus) 0225 -> Bool 0226 { 0227 switch (lhs, rhs) { 0228 case (.Unknown, .Unknown): 0229 return true 0230 case (.NotReachable, .NotReachable): 0231 return true 0232 case let (.Reachable(lhsConnectionType), .Reachable(rhsConnectionType)): 0233 return lhsConnectionType == rhsConnectionType 0234 default: 0235 return false 0236 } 0237 } 0238 0239 #endif 0240
NetworkReachabilityManager.swift:80 return networkReachabilityStatusForFlags(flags)NetworkReachabilityManager.swift:186 listener?(networkReachabilityStatusForFlags(flags))