5

I like to track the users "location" by using the device's IP address.

I've already looked for some API services like:

  • freegeoip.net
  • api.petabyet.com
  • ip-api.com

But I have no idea how to use this services to get the location of the users device.

Actually I've already looked for some Swift code snippets to get achieve the wanted result (to get the Location) but I couldn't find any code matching to the current version of Swift.

let url = NSURL(string: "http://freegeoip.net")
    let task = URLSession.shared.dataTask(with: url! as URL) {(data, response, error) in
        let httpResponse = response as? HTTPURLResponse
        if (httpResponse != nil) {

        } else { }
    }; task.resume()

The few lines above are all that I got so far. But I really hope somebody could help me with this problem.

jscs
  • 63,694
  • 13
  • 151
  • 195

1 Answers1

16

You could start by trying http://ip-api.com/json, which returns a JSON as explained on their API page.

You can then convert this JSON string to a dictionary and access the data.

func getIpLocation(completion: @escaping(NSDictionary?, Error?) -> Void)
{
    let url     = URL(string: "http://ip-api.com/json")!
    var request = URLRequest(url: url)
    request.httpMethod = "GET"

    URLSession.shared.dataTask(with: request as URLRequest, completionHandler:
    { (data, response, error) in
        DispatchQueue.main.async
        {
            if let content = data
            {
                do
                {
                    if let object = try JSONSerialization.jsonObject(with: content, options: .allowFragments) as? NSDictionary
                    {
                        completion(object, error)
                    }
                    else
                    {
                        // TODO: Create custom error.
                        completion(nil, nil)
                    }
                }
                catch
                {
                    // TODO: Create custom error.
                    completion(nil, nil)
                }
            }
            else
            {
                completion(nil, error)
            }
        }
    }).resume()
}

This function returns the dictionary or an error (after you resolve the TODO's). The completion is called on the main thread assuming you'll use the result to update the UI. If not, you can remove the DispatchQueue.main.async { }.

meaning-matters
  • 21,929
  • 10
  • 82
  • 142
  • Don't use Foundation types unless you have a very good reason to do so. Since you are casting `NSURL` and `NSMutableURLRequest` to their native Swift alternatives right away, their use is not justified at all. Moreover, there's no need to call the completion handler from the main thread. – Dávid Pásztor Jan 30 '18 at 21:48
  • That is so cool! I had no idea you could get such granular data back in such a simple JSON return. – Adrian Jan 31 '18 at 00:12