Lance Samaria
Lance Samaria

Reputation: 19592

Swift2 iOS Reachability Class and NSNotificatonCenter not receiving broadcast

I have a tabBarController with 2 tabs and a Reachability class for the internet connection.

Inside the AppDelegate's didFinishLaunching method I have a checkReachability function that checks the current network connection to see if wifi is on or off and it will broadcast a NSNotification to the second tab in either case.

Inside the second tab there is label and inside viewDidLoad there are 2 observers listening for the broadcasts. I also have 2 functions (triggered by the observers) that will change the label text based on the current network connection.

I'm using the simulator and when I toggle the wifi on/off from either the first or second tab the second tab's label text never changes.

Why is the text not changing and why are the observers not responding?

Reachability Class: FYI I got the Reachability Class from this youtube vid and I switched it from Swift 3 to Swift 2.3: https://www.youtube.com/watch?v=IlsfXjESatg&t=532s

import Foundation
import UIKit
import SystemConfiguration

protocol Utilities {
}

extension NSObject:Utilities{

    enum ReachabilityStatus {
        case notReachable
        case reachableViaWWAN
        case reachableViaWiFi
    }

    var currentReachabilityStatus: ReachabilityStatus {

        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))

        zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let defaultRouteReachability = withUnsafePointer(&zeroAddress, {
            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
        }) else {
            return .notReachable
        }

        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return .notReachable
        }

        if flags.contains(SCNetworkReachabilityFlags.Reachable) == false{
            // The target host is not reachable.
            return .notReachable
        }
        else if flags.contains(SCNetworkReachabilityFlags.IsWWAN) == true{
            // WWAN connections are OK if the calling application is using the CFNetwork APIs.
            return .reachableViaWWAN
        }

        else if flags.contains(.ConnectionRequired) == false {
            // If the target host is reachable and no connection is required then we'll assume that you're on Wi-Fi...
            return .reachableViaWiFi
        }
        else if (flags.contains(.ConnectionOnDemand) == true || flags.contains(.ConnectionOnTraffic) == true) && flags.contains(.InterventionRequired) == false {
            // The connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs and no [user] intervention is needed
            return .reachableViaWiFi
        }
        else {
            return .notReachable
        }
    }
}

AppDelegate:

class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    self.checkReachability()

    return true
}
//This function is declared inside AppDelegate 
func checkReachability(){
    if currentReachabilityStatus == .reachableViaWiFi {
            NSNotificationCenter.defaultCenter().postNotificationName("wifi", object: nil)
    }else if currentReachabilityStatus == .reachableViaWWAN{
            print("WWAN.")
    }else{
            NSNotificationCenter.defaultCenter().postNotificationName("noWifi", object: nil)
    }
}

Second Tab:

class SecondTabController: UIViewController {

@IBOutlet weak var labelTwo: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(wifiConnection), name: "wifi", object: nil)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(noConnection), name: "noWifi", object: nil)
 }

func wifiConnection(){
    self.labelTwo.text = "Wifi Connection"
 }

func noConnection(){
    self.labelTwo.text = "No Connection"
 }

deinit{
    NSNotificationCenter.defaultCenter().removeObserver(self, name: "wifi", object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: "noWifi", object: nil)
 }
}

Upvotes: 0

Views: 258

Answers (1)

Lars Blumberg
Lars Blumberg

Reputation: 21381

You're posting the notification only once to the notification center, namely when your application starts:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Your method `checkReachability` will post notifications:
    self.checkReachability()
    return true
}

However your SecondTabController is not yet created and thus it is not yet subscribed for receiving the notification that you send at app start. When notifications are posted, they are received immediately by any subscribers. Notifications "don't wait" until some subscriber is added at a later point in time.

What you probably need as a reachability manager that continues to live and posts notifications to the notification center whenever WiFi reachability changes.

You might want to use existing reachability managers, such as Alamofire's NetworkReachabilityManager as described in this question.

Upvotes: 1

Related Questions