Browse Source

Added ConnectionType to better handle OSX and tvOS and removed notifications.

There is no need to post notifications for reachability. The Listener closure should be sufficient.
Christian Noon 10 years ago
parent
commit
57f387b58d

+ 62 - 37
Source/NetworkReachabilityManager.swift

@@ -23,21 +23,6 @@
 import Foundation
 import SystemConfiguration
 
-/**
-    Defines the various states of network reachability.
-
-    - Unknown:         It is unknown whether the network is reachable.
-    - NotReachable:    The network is not reachable.
-    - ReachableOnWWAN: The network is reachable over the WWAN connection.
-    - ReachableOnWiFi: The network is reachable over the WiFi connection.
-*/
-public enum NetworkReachabilityStatus: Int {
-    case Unknown         = -1
-    case NotReachable    = 0
-    case ReachableOnWWAN = 1
-    case ReachableOnWiFi = 2
-}
-
 /**
     The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and
     WiFi network interfaces.
@@ -47,6 +32,31 @@ public enum NetworkReachabilityStatus: Int {
     request, as it's possible that an initial request may be required to establish reachability.
 */
 public class NetworkReachabilityManager {
+    /**
+        Defines the various states of network reachability.
+
+        - Unknown:         It is unknown whether the network is reachable.
+        - NotReachable:    The network is not reachable.
+        - ReachableOnWWAN: The network is reachable over the WWAN connection.
+        - ReachableOnWiFi: The network is reachable over the WiFi connection.
+    */
+    public enum NetworkReachabilityStatus {
+        case Unknown
+        case NotReachable
+        case Reachable(ConnectionType)
+    }
+
+    /**
+        Defines the various connection types detected by reachability flags.
+
+        - EthernetOrWiFi: The connection type is either over Ethernet or WiFi.
+        - WWAN:           The connection type is a WWAN connection.
+    */
+    public enum ConnectionType {
+        case EthernetOrWiFi
+        case WWAN
+    }
+
     /// A closure executed when the network reachability status changes. The closure takes a single argument: the 
     /// network reachability status.
     public typealias Listener = NetworkReachabilityStatus -> Void
@@ -54,13 +64,13 @@ public class NetworkReachabilityManager {
     // MARK: - Properties
 
     /// Whether the network is currently reachable.
-    public var isReachable: Bool { return isReachableOnWWAN || isReachableOnWiFi }
+    public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }
 
     /// Whether the network is currently reachable over the WWAN interface.
-    public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .ReachableOnWWAN }
+    public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .Reachable(.WWAN) }
 
-    /// Whether the network is currently reachable over the WiFi interface.
-    public var isReachableOnWiFi: Bool { return networkReachabilityStatus == .ReachableOnWiFi }
+    /// Whether the network is currently reachable over Ethernet or WiFi interface.
+    public var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .Reachable(.EthernetOrWiFi) }
 
     /// The current network reachability status.
     public var networkReachabilityStatus: NetworkReachabilityStatus {
@@ -170,21 +180,7 @@ public class NetworkReachabilityManager {
         guard previousFlags != flags else { return }
         previousFlags = flags
 
-        let networkReachabilityStatus = networkReachabilityStatusForFlags(flags)
-
-        listener?(networkReachabilityStatus)
-
-        dispatch_async(dispatch_get_main_queue()) {
-            let userInfo: [NSObject: AnyObject] = [
-                Notifications.NetworkReachability.StatusDidChangeUserInfoStatusKey: networkReachabilityStatus.rawValue
-            ]
-
-            NSNotificationCenter.defaultCenter().postNotificationName(
-                Notifications.NetworkReachability.StatusDidChange,
-                object: self,
-                userInfo: userInfo
-            )
-        }
+        listener?(networkReachabilityStatusForFlags(flags))
     }
 
     // MARK: - Internal - Network Reachability Status
@@ -194,16 +190,45 @@ public class NetworkReachabilityManager {
 
         var networkStatus: NetworkReachabilityStatus = .NotReachable
 
-        if !flags.contains(.ConnectionRequired) { networkStatus = .ReachableOnWiFi }
+        if !flags.contains(.ConnectionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }
 
         if flags.contains(.ConnectionOnDemand) || flags.contains(.ConnectionOnTraffic) {
-            if !flags.contains(.InterventionRequired) { networkStatus = .ReachableOnWiFi }
+            if !flags.contains(.InterventionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }
         }
 
         #if os(iOS)
-            if flags.contains(.IsWWAN) { networkStatus = .ReachableOnWWAN }
+            if flags.contains(.IsWWAN) { networkStatus = .Reachable(.WWAN) }
         #endif
 
         return networkStatus
     }
 }
+
+// MARK: -
+
+extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}
+
+/**
+    Returns whether the two network reachability status values are equal.
+
+    - parameter lhs: The left-hand side value to compare.
+    - parameter rhs: The right-hand side value to compare.
+
+    - returns: `true` if the two values are equal, `false` otherwise.
+*/
+public func ==(
+    lhs: NetworkReachabilityManager.NetworkReachabilityStatus,
+    rhs: NetworkReachabilityManager.NetworkReachabilityStatus)
+    -> Bool
+{
+    switch (lhs, rhs) {
+    case (.Unknown, .Unknown):
+        return true
+    case (.NotReachable, .NotReachable):
+        return true
+    case let (.Reachable(lhsConnectionType), .Reachable(rhsConnectionType)):
+        return lhsConnectionType == rhsConnectionType
+    default:
+        return false
+    }
+}

+ 0 - 13
Source/Notifications.swift

@@ -42,17 +42,4 @@ public struct Notifications {
         /// completed `NSURLSessionTask`.
         public static let DidComplete = "com.alamofire.notifications.task.didComplete"
     }
-
-    /// Used as a namespace for all `NetworkReachability` related notifications.
-    public struct NetworkReachability {
-        /// Notification posted when network reachability status changes. The notification `object` contains the
-        /// `NetworkReachabilityManager` reporting the status change. The `userInfo` dictionary contains the
-        /// `StatusDidChangeUserInfoStatusKey` whose value is the network reachability status as an `NSNumber` which 
-        /// will need to be converted.
-        public static let StatusDidChange = "com.alamofire.notifications.networkReachability.statusDidChange"
-
-        /// The network reachability status user info key for the `StatusDidChange` notification containing the
-        /// `NetworkReachabilityStatus` rawValue as an `NSNumber`.
-        public static let StatusDidChangeUserInfoStatusKey = "NetworkReachabilityStatus"
-    }
 }

+ 12 - 74
Tests/NetworkReachabilityManagerTests.swift

@@ -50,10 +50,10 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let manager = NetworkReachabilityManager(host: "localhost")
 
         // Then
-        XCTAssertEqual(manager?.networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(manager?.networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
         XCTAssertEqual(manager?.isReachable, true)
         XCTAssertEqual(manager?.isReachableOnWWAN, false)
-        XCTAssertEqual(manager?.isReachableOnWiFi, true)
+        XCTAssertEqual(manager?.isReachableOnEthernetOrWiFi, true)
     }
 
     func testThatAddressManagerStartsWithUnknownStatus() {
@@ -61,10 +61,10 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let manager = NetworkReachabilityManager()
 
         // Then
-        XCTAssertEqual(manager?.networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(manager?.networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
         XCTAssertEqual(manager?.isReachable, true)
         XCTAssertEqual(manager?.isReachableOnWWAN, false)
-        XCTAssertEqual(manager?.isReachableOnWiFi, true)
+        XCTAssertEqual(manager?.isReachableOnEthernetOrWiFi, true)
     }
 
     // MARK: - Tests - Listener
@@ -74,7 +74,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let manager = NetworkReachabilityManager(host: "localhost")
         let expectation = expectationWithDescription("listener closure should be executed")
 
-        var networkReachabilityStatus: NetworkReachabilityStatus?
+        var networkReachabilityStatus: NetworkReachabilityManager.NetworkReachabilityStatus?
 
         manager?.listener = { status in
             networkReachabilityStatus = status
@@ -86,7 +86,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         waitForExpectationsWithTimeout(timeout, handler: nil)
 
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
 
     func testThatAddressManagerIsNotifiedWhenStartListeningIsCalled() {
@@ -94,7 +94,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let manager = NetworkReachabilityManager()
         let expectation = expectationWithDescription("listener closure should be executed")
 
-        var networkReachabilityStatus: NetworkReachabilityStatus?
+        var networkReachabilityStatus: NetworkReachabilityManager.NetworkReachabilityStatus?
 
         manager?.listener = { status in
             networkReachabilityStatus = status
@@ -106,69 +106,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         waitForExpectationsWithTimeout(timeout, handler: nil)
 
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
-    }
-
-    // MARK: - Tests - Notifications
-
-    func testThatHostManagerSendsStatusNotificationWhenStartListeningIsCalled() {
-        // Given
-        let manager = NetworkReachabilityManager(host: "localhost")
-
-        var networkReachabilityStatus: NetworkReachabilityStatus?
-
-        expectationForNotification(Notifications.NetworkReachability.StatusDidChange, object: nil) { notification in
-            if let
-                object = notification.object,
-                userInfo = notification.userInfo,
-                number = userInfo[Notifications.NetworkReachability.StatusDidChangeUserInfoStatusKey],
-                statusValue = (number as? NSNumber)?.integerValue,
-                status = NetworkReachabilityStatus(rawValue: statusValue)
-                where manager === object
-            {
-                networkReachabilityStatus = status
-                return true
-            }
-
-            return false
-        }
-
-        // When
-        manager?.startListening()
-        waitForExpectationsWithTimeout(timeout, handler: nil)
-
-        // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
-    }
-
-    func testThatAddressManagerSendsStatusNotificationWhenStartListeningIsCalled() {
-        // Given
-        let manager = NetworkReachabilityManager()
-
-        var networkReachabilityStatus: NetworkReachabilityStatus?
-
-        expectationForNotification(Notifications.NetworkReachability.StatusDidChange, object: nil) { notification in
-            if let
-                object = notification.object,
-                userInfo = notification.userInfo,
-                number = userInfo[Notifications.NetworkReachability.StatusDidChangeUserInfoStatusKey],
-                statusValue = (number as? NSNumber)?.integerValue,
-                status = NetworkReachabilityStatus(rawValue: statusValue)
-                where manager === object
-            {
-                networkReachabilityStatus = status
-                return true
-            }
-
-            return false
-        }
-
-        // When
-        manager?.startListening()
-        waitForExpectationsWithTimeout(timeout, handler: nil)
-
-        // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
 
     // MARK: - Tests - Network Reachability Status
@@ -206,7 +144,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
 
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
 
     func testThatManagerReturnsReachableOnWiFiStatusWhenConnectionIsOnDemand() {
@@ -218,7 +156,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
 
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
 
     func testThatManagerReturnsReachableOnWiFiStatusWhenConnectionIsOnTraffic() {
@@ -230,7 +168,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
 
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
 
 #if os(iOS)
@@ -243,7 +181,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
 
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWWAN)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.WWAN))
     }
 #endif
 }