Geocoding in Swift
Have you ever wondered how a map service locates the exact address you provide without knowing its coordinates? In this article I am going to introduce you to geocoding, which is the process of obtaining information about geographical locations. Geocoding can be done in two ways.
Forward geocoding — this is when we start with a postal address or location ( e.g.:- Boston, MA) and transform it into a set of corresponding geographical coordinates ( latitude and longitude)
Reverse geocoding — this is when we obtain the address or location by giving the latitude, and longitude as inputs
In this tutorial, I will be using both Apple Maps and Google Maps to geocode an address. Before we begin, the documentation we will be referring to can be found here: Google Maps Geocoding API |Apple Maps Geocoding.
While Apple uses CLGeocoder class to call one of its forward or reverse geocoding methods, Google Maps use an external URL to initiate the service.
Let’s start with Apple geocoding!
Let’s create a new Xcode project. Before you start using CLGeocoder class add the Core Location framework to the project. At the top of the ViewController, import the Core Location framework and create a new method for forward geocoding in Apple Maps.
Let’s look at what the method does. First, we declare a CLGeocoder instance and then we invoke the geocodeAddressString(_:completionHandler:) method to geocode an address we provide as input. The completion handler returns an array of CLPlacemark instances. The Core Location framework may return multiple matches if the address is too vague or if multiple locations that exist for the same address. But here, we are particularly interested in the first placemark found. Then we get the location coordinates and print them.
There’s a chance that we might not get the location coordinates if the user-entered address is bogus or made a typo.Hence, we are checking for location coordinates before we print it. Now let’s call this method in viewDidLoad().
forwardGeocoding("675 Watertown St, Watertown St, Newton, United States")
If you run the app, you will see the expected output in the console:
lat: 42.3548226, long: -71.212563
Next, we will take a look at how to reverse geocode a given coordinate. Let’s start by writing a method for reverseGeocoding:
In scenarios where we do not get any results, display a message to the user. Similar to the forward geocoding, we are declaring a CLGeocoder instance and invoking the reverseGeocodeLocation(_:completionHandler:) method which accepts CLLocation as the input. And the completion handler returns an array of CLPlacemark instances, in which we are interested in the first item.The only detail to which we need to pay attention is the address property of the CLPlacemark instance. This is a convenience property, which I have added as an extension for the CLPlacemark class.
Now let’s call this method in viewDidLoad(). Run the app, and you will see the formatted address in the console.
reverseGeocoding(latitude: 37.484928, longitude: -122.148201)
Here’s the output:
Meta - Headquarters, Hacker Way, Menlo Park, United States
Although, that this tutorial asks the user for a set of coordinates, it is a pretty uncommon use case. Reverse geocoding is more beneficial in situations when you want to display the user an address or location depending on their current location or a place they choose on a map in your app.
Let’s move to Google Geocoding!
So, unlike Apple Maps geocoding, we have to use an external URL to acquire location data using Google Maps geocoding. Let’s start by creating a new Xcode project. And in the ViewController, add two properties: one for the base URL of the Google Maps API and another for the Api Key.
let baseUrl = "https://maps.googleapis.com/maps/api/geocode/json?"
let apikey = "YOUR_API_KEY"
Then, let’s write a method for forward geocoding using Google Maps:
This method is pretty straightforward, where it constructs a URL using the base URL, an address (given as an input parameter), and the API key, then serializes the data it finds at that URL into a JSON feed, and then parses the JSON response to fetch latitude and longitude. Now let’s call this method in viewDidLoad():
getLatLngForAddress(address: "675 Watertown St, Watertown St, Newton, United States")
Run the app and you will see this output in the console:
latitude: 42.3547979, longitude: -71.2125925
Next, let’s write a method for reverse geocoding using Google Maps:
This method is quite similar to the forward geocoding method described above, except that it uses the latitude and longitude as input parameters to obtain address information.
Now let’s call this method in viewDidLoad():
getAddressForLatLng(latitude: "37.484928", longitude: "-122.148201")
Run the app, and you should see the below output in console:
1 Hacker Way, Menlo Park, CA 94025, USA
Conclusion
In person, I am not sure which one is better than the other. But, from my personal experience I can say Google Maps returns better results in circumstances when the address is not in English or the place is in the middle of nowhere. On the other hand, Google geocoding API is free up to a maximum limit, if your app consistently generates high traffic on the Google geocoding API, you may be required to pay for additional usage of the API.
I hope you have learned something new. Thanks for reading. Happy coding!