1

For Swift 4/xcode:
I have scoured the internet for a solution to this issue, but I have yet to find a definitive, comprehensive answer that covers all of the bases. There are several on Stack that answer the question to some extent, including swift specific answers such as these or AshleyMills Reachability, but many are old and not comprehensive.
1. I want the method to check for internet connection, not just connection to wifi. Several of the methods online merely check for connection to Wi-Fi, but do not confirm that internet is available via the wifi. I want a method that only returns true if internet connection is detected.
2. This method must also return true for cellular data usage. Yes Wi-Fi can provide internet connection, but so can data. This method needs to be comprehensive enough to return true if either or both cellular/wifi internet is provided.
Lastly, a note. The fact that there isn't a full swift answer online that checks all of the boxes makes me wonder if my approach to this issue is incorrect in a more general sense. My app needs to load data from a database, which is why it needs the internet connection. This is an extremely common thing for popular apps nowadays. Apps don't crash from trying to load their data without internet connection. What I am thinking they do (which is the basis for this question) is as so:

if doesHaveInternetConnection{
    //run loading data functions
}else{
    //don't run loading data functions
}

Is this not the way it is done? If not, what is the better way to approach this problem?

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
Runeaway3
  • 1,439
  • 1
  • 17
  • 43
  • There's a big difference between checking if you are "connected" and if you can access some host on the Internet. You could use "normal" reachability to see if you are connected. If you are, then try to "ping" some specific host to see if it responds. – rmaddy Nov 01 '17 at 02:50
  • In terms of functionality for the app, what is the difference between being connected and being able to access a host? Also, wouldn't constantly trying to ping a host before launching DB data pulls for every pull slow the app down considerably? – Runeaway3 Nov 01 '17 at 02:54
  • @AlekPiasecki Using URLSession is enough for most cases. If you try to download data and there is no internet connection the error description will be The Internet connection appears to be offline. Just present an alert to the user and pass the error localized description as a message. – Leo Dabus Nov 01 '17 at 03:07
  • @LeoDabus how does the URLSession work with parse-server data calls? The calls to my data base aren't formatted as URLRequests, so how do I go about handling that? – Runeaway3 Nov 01 '17 at 03:20
  • You can just check if your server is online using a URLSession and a url from your server. You can also just fetch your url header. No need to download the url full data. https://stackoverflow.com/a/43804274/2303865 – Leo Dabus Nov 01 '17 at 03:23
  • @AlekPiasecki If you need to be notified when internet connection changes to fetch your app data you will need to use Reachability. – Leo Dabus Nov 01 '17 at 03:27
  • @LeoDabus, ok I understand how to implement this URLSession check, but if I use reachability instead, how can I use a version that accurately checks all the boxes (ie wifi internet AND cellular internet)? – Runeaway3 Nov 01 '17 at 13:34
  • 1
    @AlekPiasecki you need to use both URLSession and Reachability. When Reachability tells you flags changed you use URLSession to fetch your app data. If an error occurs just present the error returned. – Leo Dabus Nov 01 '17 at 13:47
  • @LeoDabus, sorry one more question. If all I want to do is fetch my url header of the database, how do I do this? – Runeaway3 Nov 02 '17 at 02:47
  • @AlekPiasecki You just need to create a url request for the url where your data is coming from and set the request httpMethod to "HEAD" – Leo Dabus Nov 02 '17 at 02:52
  • @AlekPiasecki you should do this only if you want to know how much data will be downloaded before starting (to decide if you can download it using the 3G/4G) otherwise you should just start fetching your data – Leo Dabus Nov 02 '17 at 02:58

2 Answers2

3

Here is a list of URLErrors when making a network request. In the list, there is an enum value called notConnectedToInternet. When you make a network request and it fails, look at the error code to find out if it is due to no connectivity or something else.

Alternatively, you can host a health-check end-point on your server. Before making any request, make a request to this end-point. If the request is successful, you can rest assured that there is internet connectivity. Although, I would highly recommend going with the first option.

Example

NOTE: The code below is in Swift 3.

URLSession.shared.dataTask(with: *URLRequest*) { (data, response, error) -> Void in
    if error != nil {
        if let e = error as? URLError, e.code == .notConnectedToInternet {
            //Not connected to internet
        } else {
            //Some other error
        }
    } else {
        //The request was successful
    }
}.resume()
Malik
  • 3,763
  • 1
  • 22
  • 35
  • I see the list and see the enum value, but could you please explain in more detail, perhaps with an example, as to how I would use this in the application? I am having trouble understanding its implementation. – Runeaway3 Nov 01 '17 at 02:56
  • That would depend on the implementation. Are you using the built in `URLSession` for making your request or are you using a third party library like Alamofire? – Malik Nov 01 '17 at 02:57
  • Updated the answer – Malik Nov 01 '17 at 03:05
  • No need to cast the error as URLError. Just present an Alert with the error localized description. check this answer I posted today https://stackoverflow.com/a/47044973/2303865 – Leo Dabus Nov 01 '17 at 03:09
  • @Malik, how would this work if my data pulls don't currently utilize `URLSession`. I used a parse-server and my datapulls are run with `findObjectInBackground`. Do I just wrap those functions in the `URLSession`? – Runeaway3 Nov 01 '17 at 03:14
  • As I said, will have to look at the implementation to suggest the appropriate approach – Malik Nov 01 '17 at 03:31
2

Using Alamofire to check interner, In Swift 4

import Foundation
import Alamofire

class Connectivity {

   class func isConnectedToInternet() ->Bool {
        return NetworkReachabilityManager()!.isReachable
   }
}

Then call this function

if Connectivity.isConnectedToInternet() {
    print("Yes! internet is available.")
    // do some tasks..
}