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 Foundation
 import SystemConfiguration
 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
     The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and
     WiFi network interfaces.
     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.
     request, as it's possible that an initial request may be required to establish reachability.
 */
 */
 public class NetworkReachabilityManager {
 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 
     /// A closure executed when the network reachability status changes. The closure takes a single argument: the 
     /// network reachability status.
     /// network reachability status.
     public typealias Listener = NetworkReachabilityStatus -> Void
     public typealias Listener = NetworkReachabilityStatus -> Void
@@ -54,13 +64,13 @@ public class NetworkReachabilityManager {
     // MARK: - Properties
     // MARK: - Properties
 
 
     /// Whether the network is currently reachable.
     /// 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.
     /// 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.
     /// The current network reachability status.
     public var networkReachabilityStatus: NetworkReachabilityStatus {
     public var networkReachabilityStatus: NetworkReachabilityStatus {
@@ -170,21 +180,7 @@ public class NetworkReachabilityManager {
         guard previousFlags != flags else { return }
         guard previousFlags != flags else { return }
         previousFlags = flags
         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
     // MARK: - Internal - Network Reachability Status
@@ -194,16 +190,45 @@ public class NetworkReachabilityManager {
 
 
         var networkStatus: NetworkReachabilityStatus = .NotReachable
         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(.ConnectionOnDemand) || flags.contains(.ConnectionOnTraffic) {
-            if !flags.contains(.InterventionRequired) { networkStatus = .ReachableOnWiFi }
+            if !flags.contains(.InterventionRequired) { networkStatus = .Reachable(.EthernetOrWiFi) }
         }
         }
 
 
         #if os(iOS)
         #if os(iOS)
-            if flags.contains(.IsWWAN) { networkStatus = .ReachableOnWWAN }
+            if flags.contains(.IsWWAN) { networkStatus = .Reachable(.WWAN) }
         #endif
         #endif
 
 
         return networkStatus
         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`.
         /// completed `NSURLSessionTask`.
         public static let DidComplete = "com.alamofire.notifications.task.didComplete"
         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")
         let manager = NetworkReachabilityManager(host: "localhost")
 
 
         // Then
         // Then
-        XCTAssertEqual(manager?.networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(manager?.networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
         XCTAssertEqual(manager?.isReachable, true)
         XCTAssertEqual(manager?.isReachable, true)
         XCTAssertEqual(manager?.isReachableOnWWAN, false)
         XCTAssertEqual(manager?.isReachableOnWWAN, false)
-        XCTAssertEqual(manager?.isReachableOnWiFi, true)
+        XCTAssertEqual(manager?.isReachableOnEthernetOrWiFi, true)
     }
     }
 
 
     func testThatAddressManagerStartsWithUnknownStatus() {
     func testThatAddressManagerStartsWithUnknownStatus() {
@@ -61,10 +61,10 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let manager = NetworkReachabilityManager()
         let manager = NetworkReachabilityManager()
 
 
         // Then
         // Then
-        XCTAssertEqual(manager?.networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(manager?.networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
         XCTAssertEqual(manager?.isReachable, true)
         XCTAssertEqual(manager?.isReachable, true)
         XCTAssertEqual(manager?.isReachableOnWWAN, false)
         XCTAssertEqual(manager?.isReachableOnWWAN, false)
-        XCTAssertEqual(manager?.isReachableOnWiFi, true)
+        XCTAssertEqual(manager?.isReachableOnEthernetOrWiFi, true)
     }
     }
 
 
     // MARK: - Tests - Listener
     // MARK: - Tests - Listener
@@ -74,7 +74,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let manager = NetworkReachabilityManager(host: "localhost")
         let manager = NetworkReachabilityManager(host: "localhost")
         let expectation = expectationWithDescription("listener closure should be executed")
         let expectation = expectationWithDescription("listener closure should be executed")
 
 
-        var networkReachabilityStatus: NetworkReachabilityStatus?
+        var networkReachabilityStatus: NetworkReachabilityManager.NetworkReachabilityStatus?
 
 
         manager?.listener = { status in
         manager?.listener = { status in
             networkReachabilityStatus = status
             networkReachabilityStatus = status
@@ -86,7 +86,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         waitForExpectationsWithTimeout(timeout, handler: nil)
         waitForExpectationsWithTimeout(timeout, handler: nil)
 
 
         // Then
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
     }
 
 
     func testThatAddressManagerIsNotifiedWhenStartListeningIsCalled() {
     func testThatAddressManagerIsNotifiedWhenStartListeningIsCalled() {
@@ -94,7 +94,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let manager = NetworkReachabilityManager()
         let manager = NetworkReachabilityManager()
         let expectation = expectationWithDescription("listener closure should be executed")
         let expectation = expectationWithDescription("listener closure should be executed")
 
 
-        var networkReachabilityStatus: NetworkReachabilityStatus?
+        var networkReachabilityStatus: NetworkReachabilityManager.NetworkReachabilityStatus?
 
 
         manager?.listener = { status in
         manager?.listener = { status in
             networkReachabilityStatus = status
             networkReachabilityStatus = status
@@ -106,69 +106,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         waitForExpectationsWithTimeout(timeout, handler: nil)
         waitForExpectationsWithTimeout(timeout, handler: nil)
 
 
         // Then
         // 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
     // MARK: - Tests - Network Reachability Status
@@ -206,7 +144,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
 
 
         // Then
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
     }
 
 
     func testThatManagerReturnsReachableOnWiFiStatusWhenConnectionIsOnDemand() {
     func testThatManagerReturnsReachableOnWiFiStatusWhenConnectionIsOnDemand() {
@@ -218,7 +156,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
 
 
         // Then
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
     }
 
 
     func testThatManagerReturnsReachableOnWiFiStatusWhenConnectionIsOnTraffic() {
     func testThatManagerReturnsReachableOnWiFiStatusWhenConnectionIsOnTraffic() {
@@ -230,7 +168,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
 
 
         // Then
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWiFi)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.EthernetOrWiFi))
     }
     }
 
 
 #if os(iOS)
 #if os(iOS)
@@ -243,7 +181,7 @@ class NetworkReachabilityManagerTestCase: BaseTestCase {
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
         let networkReachabilityStatus = manager?.networkReachabilityStatusForFlags(flags)
 
 
         // Then
         // Then
-        XCTAssertEqual(networkReachabilityStatus, .ReachableOnWWAN)
+        XCTAssertEqual(networkReachabilityStatus, .Reachable(.WWAN))
     }
     }
 #endif
 #endif
 }
 }