How do I detect change in internet connection on iOS, delegate style? - ios

I need a function to run only when the system detects there is no internet connection, then another function to run when the system detects an internet connection.
I'm thinking of something like this:
func onInternetConnection() {
//Enable actions
}
func onInternetDisconnection() {
//Disable actions, alert user
}
I will also need a way to detect when the system is reconnecting, so I can let the user know it's reconnecting, like in Facebook's Messenger.
How can I do this?
I'm using Moya/Alamofire for my network layer.

This works in case of Alamofire
import Alamofire
// In your view did load or in app delegate do like this
let reachabilityManager = NetworkReachabilityManager()
reachabilityManager.listener = { status in
switch status {
case .notReachable:
print("The network is not reachable")
self.onInternetDisconnection()
case .unknown :
print("It is unknown whether the network is reachable")
self.onInternetDisconnection() // not sure what to do for this case
case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
self.onInternetConnection()
case .reachable(.wwan):
print("The network is reachable over the WWAN connection")
self.onInternetConnection()
}
}

Alamofire and Rechability are library and that have some features to check internet connection. You can use one from that.

Related

Unable to send files between 2 device using Network Framework

I'm having trouble using network framework to transfer a collection of 1 minute video files between a recording device and a repository master device. All devices are on the same wifi. But the problem is that the distance between devices somehow is player a role in the transfer. When I have strong wifi signal on both devices, but if the devices are further than 100 feet apart, the transfer won't happen. Conversely, if both devices have very weak wifi signal (e.g. 1 bar), but are next to each other, the transfer happens without a hitch. It's as if the devices are doing something more akin to wifi direct than transfer for a LAN, which is what I really want. I'm assuming someone familiar with the framework can advise how to entirely avoid using any peer to peer wifi direct type of transfer, and force the system to transfer over the WLAN. That way all I need to do is make sure all devices have a decent wifi signal (e.g. are on the network with a decent connection), and regardless of how far they are physically from each other, the files will transfer without a hitch. Hope someone can clear this up for me.
Thanks.
Sending files between 2 devices at close range
disabled Bluetooth
Made sure both devices are on the same local network.
#Paulw11 - Thank you for the response, I have provided more details that I should have provided initially, I do apologize for that. Thanks again for the help.
We are using the mDNS approach.
func startBrowsing() {
guard browser == nil else { return }
let params = NWParameters()
params.includePeerToPeer = true
params.requiredInterfaceType = .wifi
let browser = NWBrowser(for: .bonjour(type: bonjourService, domain: nil), using: params)
self.browser = browser
browser.browseResultsChangedHandler = {
[weak self] results, changes in
guard let self = self else { return }
self.delegate?.peerBrowser(self, didUpdateResults: Array(results))
}
browser.stateUpdateHandler = { [weak self] newState in
guard let self = self else { return }
os_log("[browser] %#", newState.debugDescription)
switch newState {
case .cancelled:
break
case .failed:
os_log("[browser] restarting")
self.browser?.cancel()
self.startBrowsing()
case .ready:
break
case .setup:
break
#unknown default:
break
}
}
browser.start(queue: .main)
}
There are no such errors. I can see the standard communication is still working and because of that the sender(iPhone) will continue to send the files to iPad (receiver) with out fail but the receiver couldn’t able to receive it.
3.No
The code used to send data from one peer to another.
func sendMessage(type: UInt32, content: Data) {
guard connection?.state == .ready else {
return
}
let framerMessage = NWProtocolFramer.Message(messageType: type)
let context = NWConnection.ContentContext(identifier: "Message", metadata: [framerMessage])
connection?.send(content: content, contentContext: context, isComplete: true, completion: .idempotent)
}

Send data created while the user offline

I want to allow users to create some items while they are offline. then send created items to backend when the user reconnect to internet.I am confused, What's the proper way to achieve that?
Should I use waitsforconnectivity of URLSession and it will send the request even when the user close the app
Or should I schedule a background task? if so then how to trigger this task when user connect to the internet?
Notes: I am using Alamofire for networking
I think you're overcomplicating this.
If you're using Alamofire for networking then I wouldn't suggest the first approach as that would be mixing the usage of URLSession and Alamofire for networking and that's not a great idea.
In terms of your second approach. Why does it need to be a background task? Why can't you just check if the user is first connected to the internet, and if they are you can proceed normally. If not, then just create items and cache them somehow. Then when you reconnect to the internet you can send the cached items first as you would send normal items.
Alamofire has a built in NetworkReachabilityManager which will help you determine your network status. There's a nice example in this answer for using it.
You can use Alomafire itself do that:
NetworkManager
class NetworkManager {
//shared instance
static let shared = NetworkManager()
let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.google.com")
func startNetworkReachabilityObserver() {
reachabilityManager?.listener = { status in
switch status {
case .notReachable:
print("The network is not reachable")
case .unknown :
print("It is unknown whether the network is reachable")
case .reachable(.ethernetOrWiFi):
print("The network is reachable over the WiFi connection")
case .reachable(.wwan):
print("The network is reachable over the WWAN connection")
}
}
// start listening
reachabilityManager?.startListening()
}
}
Reachability Observer
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// add network reachability observer on app start
NetworkManager.shared.startNetworkReachabilityObserver()
return true
}
}

Check if device is connected to the internet in Swift2

I'm trying to find a way to check to see if my application has a connection to the internet for my application. I've tried using the various Reachability libraries you can find on GitHub which cause compiling errors for my project. (Makes other libraries not available, for some reason) and I've also tried the JustHTTP library for making a GET request to http://www.google.com but it fails every time.
I'm not exactly sure what the issue is here, but I'd like to know how some of you go about validating a connection to the internet before allowing users to use the application.
This question was marked as a duplicated and linked to a question which used the Reachability library provided by AshleyMills. Which I had stated I've attempted using these libraries already, but could not do to confliction errors in my project. The GET request code provided on this question is also out of date, and does not work on SWIFT2. This linked question also assumes that I do not need to support anything under iOS 9 which seems like a bad practice. My minimum support is iOS8
Swift 2.x (requires Reachability)
do {
let reachable = try Reachability.init(hostname: "https:\\www.google.com")
if(reachable.currentReachabilityStatus == Reachability.NetworkStatus.ReachableViaWWAN){
//Device is connected thru 3G/4G/LTE
}else if(reachable.currentReachabilityStatus == Reachability.NetworkStatus.ReachableViaWiFi){
//Device is connected thru WiFi
}else{
//Device is not connected to the internet
}
}catch{
//Device is not connected to the internet
}
You can get Reachability here
Add Reachability.swift to your project.
And try below code.
do
{
let connected: Bool = try Reachability.reachabilityForInternetConnection().isReachable()
if connected == true
{
print("Internet connection OK")
}
else
{
print("Internet connection FAILED")
let alert = UIAlertView(title: "No Internet Connection", message: "Make sure your device is connected to the internet.", delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
}
catch
{
print("Handle Exception")
}
This code might help. You need the Reachability lib, this snippet can give you an example to check if your device reaches Internet via WiFi or via 4G/3G/LTE
func checkNetworkStatus() -> Bool {
let reachability: Reachability = Reachability.reachabilityForInternetConnection()
let networkStatus = reachability.currentReachabilityStatus().rawValue;
var isAvailable = false;
switch networkStatus {
case (NotReachable.rawValue):
isAvailable = false;
break;
case (ReachableViaWiFi.rawValue):
isAvailable = true;
break;
case (ReachableViaWWAN.rawValue):
isAvailable = true;
break;
default:
isAvailable = false;
break;
}
return isAvailable;
}
If your request fail all the time maybe it's because you are not doing them over https but over http. It has to do with ATS on iOS 9 - this blog explains very well how to disable (if you want - not recommended) ATS http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/

Observe WiFi / 3G changes

Is it possible to observe when the user switch between WiFi and cellular data (3G/4G)?
Maybe something in Reachability, but I don't know what.
The easiest way I think is import CoreTelephony and observe CTRadioAccessTechnologyDidChangeNotification and then switch over that like this:
let networkInfo = CTTelephonyNetworkInfo()
let radio = networkInfo.currentRadioAccessTechnology
guard let currentRadio = radio else {
print("No radio info available")
return
}
switch currentRadio {
case CTRadioAccessTechnologyLTE,
CTRadioAccessTechnologyHSDPA: //3.5G "T-Mobile 4G"
print("This is 4G / LTE")
case CTRadioAccessTechnologyeHRPD, //3.5G "Verizon 3G"
CTRadioAccessTechnologyHSUPA,
CTRadioAccessTechnologyWCDMA,
CTRadioAccessTechnologyCDMAEVDORev0,
CTRadioAccessTechnologyCDMAEVDORevA,
CTRadioAccessTechnologyCDMAEVDORevB:
print("This is 3G")
case CTRadioAccessTechnologyGPRS,
CTRadioAccessTechnologyCDMA1x
CTRadioAccessTechnologyEdge:
print("This is 2G")
default:
print("Unknown cellular network type")
}
If you listen for that notification while also using standard Reachability, you can use this switch to get cell network type. You will need currentReachabilityStatus to independently check for a WiFi connection. As far as I am aware, in Swift you need to set up a bridging header to use Apple's Reachability class but there are Swift implementations available as well on github.
Yes Reachability provide you with type of network connected. It gives 3 different status - Not Connected to internet, Connected to Wifi, Connected to Mobile Data.
NetworkStatus status = [reachability currentReachabilityStatus];
if(status == NotReachable)
{
//No Connectivity to Internet
}
else if (status == ReachableViaWiFi)
{
//Connected via WiFi
}
else if (status == ReachableViaWWAN)
{
//Connected via Mobile Data
}

How to check when ios device just lost connection to internet

how to detect losing connection to network as fast as it can be
now im using reachabitity framework for swift and it takes abouut 3 sec to detect that there is no network so user can make the app crash
here how i check it :
func setupReachability() {
do {
self.reachability = try Reachability.reachabilityForInternetConnection()
} catch {
print("Cannot setup reachability monitoring")
return
}
self.reachability!.whenReachable = { reachability in
self.loginButton(true)
}
self.reachability!.whenUnreachable = { reachability in
self.loginButton(false)
}
do { try self.reachability!.startNotifier() } catch {
print("Cannot start reachability monitoring")
return
}
print("Started reachability")
}
You always, ALWAYS, must handle errors in your connections. You absolutely cannot rely on Reachability. You also cannot rely that your connection goes to the server that you want to connect to. It is possible and practically happens a lot that you get a reply from a totally different server in a totally different format than you expected, and you need to handle that. (Take your app to the nearest Starbucks and check whether it survives).

Resources