Forward Geocoding in iOS4 and iOS5

Forward Geocoding

It is a common scenario that every developer has run into.

Locate places near me based upon a particular address and/or zip code.

In order to get the correct results the address needs to be converted to a lat/long coordinate. With iOS5 Apple has provided us with CLGeoCoder class which has convience methods for reverse/forward geocoding. Unfortunately, there isn’t really any built-in functionality for iOS4. Most current apps still have to support iOS4 so what are developers doing to fill the gap? Write their implementations for multiple OS support. Below is what I use.

** Note: I did use Sergio Martínez-Losa Del Rincón article as a starting point for the iOS4 support.

Techniques

  • Google’s Map API
  • CLGeoCoder
  • Objective-C blocks for callback
  • Grand Central Dispatch

Implementation

iOS5

I tackled the easiest solution first. Utilizing iOS5’s CLGeoCoding geocodeAddressString:completionHandler: . However, when I first use the method I kept getting back a location of {0.0,0.0} in my log. The reason being that I was neglecting the fact that the method executes asynchronously and doesn’t return its value. Hmmm….

Not too much of a hurdle thanks to the implementation of block handling. By adding a completionHandler to my own method I was able to provide a callback with the appropriate coordinate that I need after the request had finished.

iOS4

Duplicating the ease of the iOS5 functionality was a bit more involved. I created a category method on NSString (see the above referenced article for code origin. I did make updates to it.) for making a call to the Google Maps API and return their forward coding result. The method itself isn’t asynchronous because I wanted to leave the decision of whether or not to call the method async or sync up to the developer. To provide asynchrous support was easy just by utiliizing GCD.

Decision Time

Deciding which code block should the calling method execute was the final task to finish. Once again this was extremely simple.

if (NSClassFromString(@“CLGeocoder”)) { // ios5 } else { // everything else. in this case we are assuming there isn’t support for iOS3.x }

Code