Sfoglia il codice sorgente

Some code refactoring

Remove reachabilityForLocalWiFi() - see Apple’s Reachability readme.md
Move public / private methods / vars to extensions
Some renaming
Update iOS Sample app
Ashley Mills 9 anni fa
parent
commit
dbb7049365

+ 99 - 132
Reachability/Reachability.swift

@@ -72,15 +72,17 @@ public class Reachability: NSObject {
         }
     }
 
-    // MARK: - *** Public properties ***
     public var whenReachable: NetworkReachable?
     public var whenUnreachable: NetworkUnreachable?
     public var reachableOnWWAN: Bool
-    public var notificationCenter = NotificationCenter.default
+
+    public var currentReachabilityString: String {
+        return "\(currentReachabilityStatus)"
+    }
 
     public var currentReachabilityStatus: NetworkStatus {
-        if isReachable() {
-            if isReachableViaWiFi() {
+        if isReachable {
+            if isReachableViaWiFi {
                 return .ReachableViaWiFi
             }
             if isRunningOnDevice {
@@ -89,29 +91,46 @@ public class Reachability: NSObject {
         }
         return .NotReachable
     }
-
-    public var currentReachabilityString: String {
-        return "\(currentReachabilityStatus)"
-    }
-
+    
     private var previousFlags: SCNetworkReachabilityFlags?
     
-    // MARK: - *** Initialisation methods ***
+    private var isRunningOnDevice: Bool = {
+        #if (arch(i386) || arch(x86_64)) && os(iOS)
+            return false
+        #else
+            return true
+        #endif
+    }()
+    
+    private var notifierRunning = false
+    private var reachabilityRef: SCNetworkReachability?
+    
+    private let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability")
     
     required public init(reachabilityRef: SCNetworkReachability) {
         reachableOnWWAN = true
         self.reachabilityRef = reachabilityRef
     }
     
-    public convenience init(hostname: String) throws {
-        
-        guard let nodename = (hostname as NSString).utf8String,
-            let ref = SCNetworkReachabilityCreateWithName(nil, nodename) else { throw ReachabilityError.FailedToCreateWithHostname(hostname) }
+    deinit {
+        stopNotifier()
 
-        self.init(reachabilityRef: ref)
+        reachabilityRef = nil
+        whenReachable = nil
+        whenUnreachable = nil
     }
+}
 
-    public class func reachabilityForInternetConnection() throws -> Reachability {
+public extension Reachability {
+    
+    convenience init(hostname: String) throws {
+        
+        guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { throw ReachabilityError.FailedToCreateWithHostname(hostname) }
+        
+        self.init(reachabilityRef: ref)
+    }
+    
+    class func reachabilityForInternetConnection() throws -> Reachability {
         
         var zeroAddress = sockaddr_in()
         zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
@@ -123,27 +142,10 @@ public class Reachability: NSObject {
         
         return Reachability(reachabilityRef: ref)
     }
-
-    public class func reachabilityForLocalWiFi() throws -> Reachability {
-
-        var localWifiAddress: sockaddr_in = sockaddr_in(sin_len: __uint8_t(0), sin_family: sa_family_t(0), sin_port: in_port_t(0), sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
-        localWifiAddress.sin_len = UInt8(sizeofValue(localWifiAddress))
-        localWifiAddress.sin_family = sa_family_t(AF_INET)
-
-        // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
-        let address: UInt32 = 0xA9FE0000
-        localWifiAddress.sin_addr.s_addr = in_addr_t(address.bigEndian)
-
-        guard let ref = withUnsafePointer(&localWifiAddress, {
-            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
-        }) else { throw ReachabilityError.FailedToCreateWithAddress(localWifiAddress) }
-        
-        return Reachability(reachabilityRef: ref)
-    }
-
+    
     // MARK: - *** Notifier methods ***
-    public func startNotifier() throws {
-
+    func startNotifier() throws {
+        
         guard let reachabilityRef = reachabilityRef, !notifierRunning else { return }
         
         var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
@@ -153,96 +155,89 @@ public class Reachability: NSObject {
             stopNotifier()
             throw ReachabilityError.UnableToSetCallback
         }
-
+        
         if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) {
             stopNotifier()
             throw ReachabilityError.UnableToSetDispatchQueue
         }
-
+        
         // Perform an intial check
-        reachabilitySerialQueue.async { 
+        reachabilitySerialQueue.async {
             let flags = self.reachabilityFlags
             self.reachabilityChanged(flags: flags)
         }
         
         notifierRunning = true
     }
-
-    public func stopNotifier() {
+    
+    func stopNotifier() {
         defer { notifierRunning = false }
         guard let reachabilityRef = reachabilityRef else { return }
-
+        
         SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
         SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
     }
     
     // MARK: - *** Connection test methods ***
-    public func isReachable() -> Bool {
+    var isReachable: Bool {
         let flags = reachabilityFlags
-        return isReachableWithFlags(flags:flags)
+        return isReachable(flags:flags)
     }
-
-    public func isReachableViaWWAN() -> Bool {
+    
+    var isReachableViaWWAN: Bool {
         
         let flags = reachabilityFlags
         
         // Check we're not on the simulator, we're REACHABLE and check we're on WWAN
         return isRunningOnDevice && isReachable(flags:flags) && isOnWWAN(flags:flags)
     }
-
-    public func isReachableViaWiFi() -> Bool {
+    
+    var isReachableViaWiFi: Bool {
         
         let flags = reachabilityFlags
         
         // Check we're reachable
-        if !isReachable(flags:flags) {
-            return false
-        }
+        guard isReachable(flags:flags) else { return false }
         
-        // Must be on WiFi if reachable but not on an iOS device (i.e. simulator)
-        if !isRunningOnDevice {
-            return true
-        }
+        // If reachable we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi
+        guard isRunningOnDevice else { return true }
         
         // Check we're NOT on WWAN
         return !isOnWWAN(flags:flags)
     }
-
-    // MARK: - *** Private methods ***
-    private var isRunningOnDevice: Bool = {
-        #if (arch(i386) || arch(x86_64)) && os(iOS)
-            return false
-        #else
-            return true
-        #endif
-    }()
-
-    private var notifierRunning = false
-    private var reachabilityRef: SCNetworkReachability?
     
-    private let reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability")
+    override var description: String {
+        
+        let W = isRunningOnDevice ? (isOnWWAN(flags: reachabilityFlags) ? "W" : "-") : "X"
+        let R = isReachable(flags: reachabilityFlags) ? "R" : "-"
+        let c = isConnectionRequired(flags: reachabilityFlags) ? "c" : "-"
+        let t = isTransientConnection(flags: reachabilityFlags) ? "t" : "-"
+        let i = isInterventionRequired(flags: reachabilityFlags) ? "i" : "-"
+        let C = isConnectionOnTraffic(flags: reachabilityFlags) ? "C" : "-"
+        let D = isConnectionOnDemand(flags: reachabilityFlags) ? "D" : "-"
+        let l = isLocalAddress(flags: reachabilityFlags) ? "l" : "-"
+        let d = isDirect(flags: reachabilityFlags) ? "d" : "-"
+        
+        return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)"
+    }
+}
 
-    private func reachabilityChanged(flags:SCNetworkReachabilityFlags) {
+private extension Reachability {
+    
+    func reachabilityChanged(flags:SCNetworkReachabilityFlags) {
         
         guard previousFlags != flags else { return }
         
-        if isReachableWithFlags(flags:flags) {
-            if let block = whenReachable {
-                block(self)
-            }
-        } else {
-            if let block = whenUnreachable {
-                block(self)
-            }
-        }
-
-        notificationCenter.post(name: ReachabilityChangedNotification, object:self)
-
+        let block = isReachable(withFlags: flags) ? whenReachable : whenUnreachable
+        block?(self)
+        
+        NotificationCenter.default.post(name: ReachabilityChangedNotification, object:self)
+        
         previousFlags = flags
     }
-
-    private func isReachableWithFlags(flags:SCNetworkReachabilityFlags) -> Bool {
-
+    
+    func isReachable(withFlags flags:SCNetworkReachabilityFlags) -> Bool {
+        
         if !isReachable(flags: flags) {
             return false
         }
@@ -263,67 +258,67 @@ public class Reachability: NSObject {
     
     // WWAN may be available, but not active until a connection has been established.
     // WiFi may require a connection for VPN on Demand.
-    private func isConnectionRequired() -> Bool {
+    func isConnectionRequired() -> Bool {
         return connectionRequired()
     }
-
-    private func connectionRequired() -> Bool {
+    
+    func connectionRequired() -> Bool {
         let flags = reachabilityFlags
         return isConnectionRequired(flags: flags)
     }
-
+    
     // Dynamic, on demand connection?
-    private func isConnectionOnDemand() -> Bool {
+    func isConnectionOnDemand() -> Bool {
         let flags = reachabilityFlags
         return isConnectionRequired(flags: flags) && isConnectionOnTrafficOrDemand(flags: flags)
     }
-
+    
     // Is user intervention required?
-    private func isInterventionRequired() -> Bool {
+    func isInterventionRequired() -> Bool {
         let flags = reachabilityFlags
         return isConnectionRequired(flags: flags) && isInterventionRequired(flags: flags)
     }
-
-    private func isOnWWAN(flags:SCNetworkReachabilityFlags) -> Bool {
+    
+    func isOnWWAN(flags:SCNetworkReachabilityFlags) -> Bool {
         #if os(iOS)
             return flags.contains(.isWWAN)
         #else
             return false
         #endif
     }
-    private func isReachable(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isReachable(flags:SCNetworkReachabilityFlags) -> Bool {
         return flags.contains(.reachable)
     }
-    private func isConnectionRequired(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isConnectionRequired(flags:SCNetworkReachabilityFlags) -> Bool {
         return flags.contains(.connectionRequired)
     }
-    private func isInterventionRequired(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isInterventionRequired(flags:SCNetworkReachabilityFlags) -> Bool {
         return flags.contains(.interventionRequired)
     }
-    private func isConnectionOnTraffic(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isConnectionOnTraffic(flags:SCNetworkReachabilityFlags) -> Bool {
         return flags.contains(.connectionOnTraffic)
     }
-    private func isConnectionOnDemand(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isConnectionOnDemand(flags:SCNetworkReachabilityFlags) -> Bool {
         return flags.contains(.connectionOnDemand)
     }
     func isConnectionOnTrafficOrDemand(flags:SCNetworkReachabilityFlags) -> Bool {
         return !flags.intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty
     }
-    private func isTransientConnection(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isTransientConnection(flags:SCNetworkReachabilityFlags) -> Bool {
         return flags.contains(.transientConnection)
     }
-    private func isLocalAddress(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isLocalAddress(flags:SCNetworkReachabilityFlags) -> Bool {
         return flags.contains(.isLocalAddress)
     }
-    private func isDirect(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isDirect(flags:SCNetworkReachabilityFlags) -> Bool {
         return flags.contains(.isDirect)
     }
-    private func isConnectionRequiredOrTransient(flags:SCNetworkReachabilityFlags) -> Bool {
+    func isConnectionRequiredOrTransient(flags:SCNetworkReachabilityFlags) -> Bool {
         let testcase:SCNetworkReachabilityFlags = [.connectionRequired, .transientConnection]
         return flags.intersection(testcase) == testcase
     }
-
-    private var reachabilityFlags: SCNetworkReachabilityFlags {
+    
+    var reachabilityFlags: SCNetworkReachabilityFlags {
         
         guard let reachabilityRef = reachabilityRef else { return SCNetworkReachabilityFlags() }
         
@@ -338,32 +333,4 @@ public class Reachability: NSObject {
             return SCNetworkReachabilityFlags()
         }
     }
-
-    override public var description: String {
-
-        var W: String
-        if isRunningOnDevice {
-            W = isOnWWAN(flags: reachabilityFlags) ? "W" : "-"
-        } else {
-            W = "X"
-        }
-        let R = isReachable(flags: reachabilityFlags) ? "R" : "-"
-        let c = isConnectionRequired(flags: reachabilityFlags) ? "c" : "-"
-        let t = isTransientConnection(flags: reachabilityFlags) ? "t" : "-"
-        let i = isInterventionRequired(flags: reachabilityFlags) ? "i" : "-"
-        let C = isConnectionOnTraffic(flags: reachabilityFlags) ? "C" : "-"
-        let D = isConnectionOnDemand(flags: reachabilityFlags) ? "D" : "-"
-        let l = isLocalAddress(flags: reachabilityFlags) ? "l" : "-"
-        let d = isDirect(flags: reachabilityFlags) ? "d" : "-"
-
-        return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)"
-    }
-
-    deinit {
-        stopNotifier()
-
-        reachabilityRef = nil
-        whenReachable = nil
-        whenUnreachable = nil
-    }
 }

+ 2 - 2
ReachabilityMacSample/AppDelegate.swift

@@ -10,10 +10,10 @@ import Cocoa
 
 @NSApplicationMain
 class AppDelegate: NSObject, NSApplicationDelegate {
-  func applicationDidFinishLaunching(aNotification: NSNotification) {
+  func applicationDidFinishLaunching(_ aNotification: Notification) {
   }
 
-  func applicationWillTerminate(aNotification: NSNotification) {
+  func applicationWillTerminate(_ aNotification: Notification) {
   }
 }
 

+ 1 - 1
ReachabilitySample/Info.plist

@@ -15,7 +15,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.2-beta2</string>
+	<string>3.0-beta4</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 9 - 9
ReachabilitySample/ViewController.swift

@@ -25,13 +25,13 @@ class ViewController: UIViewController {
 
         // After 5 seconds, stop and re-start reachability, this time using a hostname
         let dispatchTime = DispatchTime.now() + DispatchTimeInterval.seconds(5)
-        DispatchQueue.main.after(when: dispatchTime) {
+        DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
             self.stopNotifier()
             self.setupReachability(hostName: "google.com", useClosures: true)
             self.startNotifier()
 
             let dispatchTime = DispatchTime.now() + DispatchTimeInterval.seconds(5)
-            DispatchQueue.main.after(when: dispatchTime) {
+            DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
                 self.stopNotifier()
                 self.setupReachability(hostName: "invalidhost", useClosures: true)
                 self.startNotifier()            }
@@ -48,7 +48,7 @@ class ViewController: UIViewController {
             let reachability = try hostName == nil ? Reachability.reachabilityForInternetConnection() : Reachability(hostname: hostName!)
             self.reachability = reachability
         } catch ReachabilityError.FailedToCreateWithAddress(let address) {
-            networkStatus.textColor = UIColor.red()
+            networkStatus.textColor = .red
             networkStatus.text = "Unable to create\nReachability with address:\n\(address)"
             return
         } catch {}
@@ -74,7 +74,7 @@ class ViewController: UIViewController {
         do {
             try reachability?.startNotifier()
         } catch {
-            networkStatus.textColor = UIColor.red()
+            networkStatus.textColor = .red
             networkStatus.text = "Unable to start\nnotifier"
             return
         }
@@ -89,10 +89,10 @@ class ViewController: UIViewController {
     
     func updateLabelColourWhenReachable(_ reachability: Reachability) {
         print("\(reachability.description) - \(reachability.currentReachabilityString)")
-        if reachability.isReachableViaWiFi() {
-            self.networkStatus.textColor = UIColor.green()
+        if reachability.isReachableViaWiFi {
+            self.networkStatus.textColor = .green
         } else {
-            self.networkStatus.textColor = UIColor.blue()
+            self.networkStatus.textColor = .blue
         }
         
         self.networkStatus.text = reachability.currentReachabilityString
@@ -101,7 +101,7 @@ class ViewController: UIViewController {
     func updateLabelColourWhenNotReachable(_ reachability: Reachability) {
         print("\(reachability.description) - \(reachability.currentReachabilityString)")
 
-        self.networkStatus.textColor = UIColor.red()
+        self.networkStatus.textColor = .red
         
         self.networkStatus.text = reachability.currentReachabilityString
     }
@@ -110,7 +110,7 @@ class ViewController: UIViewController {
     func reachabilityChanged(_ note: Notification) {
         let reachability = note.object as! Reachability
         
-        if reachability.isReachable() {
+        if reachability.isReachable {
             updateLabelColourWhenReachable(reachability)
         } else {
             updateLabelColourWhenNotReachable(reachability)