0

Everyone who reads it! My iOS program needs to be connected to Internet and if connection is lost, report to me immidiatly. It could be anything: Airplane Mode, changed modes from LTE to 3G or Edge, turning WiFi on or off, going from WiFi to cellular signal or opposite. I already have a code, which allows to check is Internet available or not. There it is (from How to use SCNetworkReachability in Swift):

import SystemConfiguration

    func connectedToNetwork() -> Bool {
        var zeroAddress = sockaddr_in()
        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 false
        }
        var flags : SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return false
        }
        let isReachable = flags.contains(.Reachable)
        let needsConnection = flags.contains(.ConnectionRequired)
        return (isReachable && !needsConnection)
    }

But this code works only if I call connectedToNetwork() function. For example, when I am sending POST request to server or pressing button. I could use a timer to execute this code every 10 seconds, but I think there has to be a better way. So I want to catch system events if something with connecting happens and then execute this code or get information about Internet was lost or available now. Thank you for future help!

Community
  • 1
  • 1
Alex
  • 1,038
  • 2
  • 12
  • 32
  • Your code seems to be from http://stackoverflow.com/questions/25623272/how-to-use-scnetworkreachability-in-swift/25623647#25623647. If you look at the end of the answer then you'll find links to more information about how to register a callback function that is called on network changes. – Martin R Feb 02 '16 at 07:40
  • Yes, Martin, it is that code. But can you improve yours answer to explain how use it through NSNotification or observer? – Alex Feb 02 '16 at 08:07
  • I need to force it work through NSNotification center. As I understand, I am am adding observer and then catching it's reply. – Alex Feb 02 '16 at 08:50

3 Answers3

0

You can use Reachability class to get notification when network status has changed. Refer https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html for documentation as well as sample code on integrating Reachability. It gives you kReachabilityChangedNotification notification which is broadcasted when network status has changed. Once you get the notification you can check whether network is available or not. Above link also provides sample project demonstrating use of Reachability class

UPDATE

Refer Detecting Network Connectivity Changes using Reachability, NSNotification and Network Link Conditioner in Swift for code on how to implement it.

UPDATE Currently Reachability class is available only in objective C. SO you can refer this How to call Objective-C code from Swift to use objective C code in your swift project.

Community
  • 1
  • 1
Vishnu gondlekar
  • 3,896
  • 21
  • 35
  • Thank you for your answer. Is it possible to see any not hard code example of it? – Alex Feb 02 '16 at 07:53
  • Thank you but it is almost. Guy in those example uses .h and .m files. It is not pure swift and I need swift solution... – Alex Feb 02 '16 at 10:01
  • And, one more: do you know what to import in program to force Reachability work? import SystemConfiguration is not enough... – Alex Feb 02 '16 at 10:08
  • Just importing Reachability.h will do, as it will include necessary frameworks. – Vishnu gondlekar Feb 02 '16 at 10:18
  • Is it possible just catch something like this: "network state changed in system" event? I just need only this, I don't need to know is google working or not. I heard it is possible on Android... – Alex Feb 02 '16 at 10:55
  • Yes, `kReachabilityChangedNotification ` provides you with that. Whenever network state is changed it gets triggered. – Vishnu gondlekar Feb 02 '16 at 11:08
  • Check my solution, please, and, if it possible, show how to use kReachabilityChangedNotification – Alex Feb 02 '16 at 13:59
  • Ok, thank you, but I will wait until Apple will port this function on Swift or creates similar for it. By now, if you want, you can test my solution and tell how it is. – Alex Feb 02 '16 at 15:24
0

You should use Reachability module. This gives amazing callbacks and real time detection of network state and changes.

https://github.com/ashleymills/Reachability.swift

Pradeep K
  • 3,671
  • 1
  • 11
  • 15
  • Thank you for your answer but I am not ready to use modules from GitHub, because they are usually too hard and and too powerful. I just need simple code example... – Alex Feb 02 '16 at 07:52
0

Ok, I found a simple answer:

1) create file .swift and paste it there:

 import Foundation
 import SystemConfiguration

 var internetAvailable: Bool = true

 let ReachabilityStatusChangedNotification = "ReachabilityStatusChangedNotification"

 func isInternetAvailable() {
    let hostToConnect = "google.com"
    var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
    let isAvailable = SCNetworkReachabilityCreateWithName(nil, hostToConnect)!

    SCNetworkReachabilitySetCallback(isAvailable, { (_, flags, _) in
        var reachabilityFlags = SCNetworkReachabilityFlags()
        reachabilityFlags = flags

        if (reachabilityFlags.contains(.Reachable)) && !(reachabilityFlags.contains(.ConnectionRequired)) {
            if reachabilityFlags.contains(.IsWWAN) {
                internetAvailable = true
                print("Online Cellular")
            } else {
                internetAvailable = true
                print("Online WiFi")
            }
        } else {
            internetAvailable = false
            print("Offline")
        }

        NSNotificationCenter.defaultCenter().postNotificationName(ReachabilityStatusChangedNotification, object: nil)

        }, &context)

    SCNetworkReachabilityScheduleWithRunLoop(isAvailable, CFRunLoopGetMain(), kCFRunLoopCommonModes)
 }

2) In AppDelegate.swift find function application and replace it or add it with this:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("networkStatusChanged:"), name: ReachabilityStatusChangedNotification, object: nil)
        isInternetAvailable()
        return true
    }

3) In AppDelegate.swift also add this function:

func networkStatusChanged(notification: NSNotification) {
    }

4) Done! Function networkStatusChanged will be executed any time somethings changes in network connection! And if you need something to do which requires Internet do it like this:

if internetAvailable {
//Do what you need, for example send JSON request on server
}
Alex
  • 1,038
  • 2
  • 12
  • 32