Introduction
Back in September I posted a large post going over all the components required to implement the MapKit in your application. The MapKit is a framework introduced in iPhone OS 3.0 and allows developers to easily take advantage of Google’s mapping technology. In my first post I go over how to present a map as well as annotate the map with custom badges to highlight points of interest. The MapKit also gives developers access to reverse geocoding services from Google which I will cover in this post.
Reverse Geocoding
A users location is defined by coordinates. When using the Core Location services, or specifying where a map should center its view, coordinates will be the units developers will be working with. This is all well and good for presenting mapping information visually but there is a whole other set of information that can be derived from a set of coordinates.
- Country
- State
- Zip Code
- Address
Google provides the service to translate any coordinate set to an MKPlacemark object. An MKPlacemark object contains properties to access all this information. Let’s look into the process of getting this object.
Step 1
The first thing you need to do is make a “View Based Application”. Now we need to is pick a set of coordinates we want to use. I have decided to use the address of Arizona State University.
Longitude: -111.936619;
Latitude: 33.416199;
Make your AppDelegates .m file look like this:
- (void)applicationDidFinishLaunching:(UIApplication *)application { // Override point for customization after app launch [window addSubview:viewController.view]; [window makeKeyAndVisible]; CLLocationCoordinate2D coord; coord.longitude = -111.936619; coord.latitude = 33.416199; MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:coord]; [geocoder setDelegate:self]; [geocoder start] }
Step 2
Now we need to implement the MKReverseGeocoderDelegate methods. There are only 2 delegate methods:
Called when an error occurs when fetching the reverse geocoder object
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error
Called when the ReverseGeocode object is successfully returned.
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
Step 3
Now we have a MKPlacemark object to use. An MKPlacemark object conforms to the MKAnnotation protocol. So these objects could be added as annotations to an MKMapView. For more information on MKAnnotations reference part 1. The MKPlacemark object contains the following properties that you can access to use in your application.
To see all of these values make the success delegate method look like this:
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark { NSLog(@"The geocoder has returned: %@", [placemark addressDictionary]); }
You should see this output:
2009-12-22 11:23:05.492 ReverseGeocoder[2591:207] The geocoder has returned: { City = Tempe; Country = "United States"; CountryCode = US; FormattedAddressLines = ( "200-206 E Lemon St", "Tempe, AZ 85281", USA ); State = Arizona; Street = "200-206 E Lemon St"; SubAdministrativeArea = Maricopa; SubThoroughfare = "200-206"; Thoroughfare = "E Lemon St"; ZIP = 85281; }



11 Comments
Hi, I tried this example, but now I’m stuck with the line “[geocoder setDelegate:self];” part, as I try to build this example, a warning message returns, saying that “class ‘TestMapAppDelegate’ does not implement the ‘MKReverseGeocoderDelegate’ protocol”, in which “TestMap” is my test project name. So what am I doing wrong on this? I look up several examples through internet, they are almost the same way.
@steve
Collin forgot to show the header file for this application. The class signature should look something like this:
@interface iCodeMapViewController : UIViewController< MKReverseGeocoderDelegate>
{
…
}
That should solve your warning. I will make sure he adds that to the tutorial.
Thanks for your advice. Now I’m a little confused, since in the beginning of the article, the codes are placed in the AppDelegates.m file, but with your advice, I need to move these codes to ViewController.m file, so that I can build this project without problem.
Next, I added a line in “(void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error” method to display the error message:
NSLog(@”reverseGeocoder:%@ didFailWithError:%@”, geocoder, error);
But after running this project, the only thing I get is error message, instead of the expected output:
/SourceCache/ProtocolBuffer/ProtocolBuffer-26/Runtime/PBRequester.m:523 server returned error: 503
2010-01-07 11:19:44.083 map2[1770:207] reverseGeocoder: didFailWithError:Error Domain=PBRequesterErrorDomain Code=6001 “Operation could not be completed. (PBRequesterErrorDomain error 6001.)”
I don’t get it, what did I do wrong this time?
@steve,
I’ll have Collin update the source code for this in the next few days so you can see it.
Hello,
Nice work! But I too would like to see the whole files listed preferably available for download to actually work with it, that would make it more useful for understanding how to implement it and how to pull the information out of the object properly. Thanks in advance!
Kirk
Greetings,
I have a question, though somewhat out of scope for this post; I’ve been trying to update a UITableViewCell’s detailTextLabel from the reverseGeocoder:didFindPlacemark: delegate, with apparent no success.
The table cell *is* updated, but the update does not show on the screen until the table view is redrawn. I’ve tried reloading the table data with no luck, and I was starting to think that this might be a cause of the geocoder running its own thread, and that the ui update does not happen in the main thread? is the geocoder running its own thread? In that case, should performSelectorOnMainThread do the trick?
Great work on the tutorials! Keep’em coming!
torg
Google Voice is an absolute lifesaver. The features of it are amazing, for example the ability to screening calls. I have invites if anyone wants one. Also I hope that Apple rethinks the Google Voice app, hwo could such an killer program get not accepted by Apple?
Hi guys, I’m trying to detect current user address using MKReverseGeocoder passing coordinates obtained via CLLocation class. Reading MKReverseGeocoder Class Reference I noticed that:
The Google terms of service require that the reverse geocoding service be used in conjunction with a Google map; take this into account when designing your application’s user interface.
i have tried this programe but it gives me following error
“/SourceCache/GoogleMobileMaps/GoogleMobileMaps-217.2/googlenav/mac/Loader.mm:257 server returned error: 407″
even i tried apples mapkit example of weathermap,worldcities ,it gives me same error.
can any one knows why it comes ,
I was also facing the same problem. In my case, the problem was the proxy settings. I t required a authentication , so I bypassed proxy for *maps.google.com* and worked fine thereafter.
That is a handy write-up, not thay hard to read. Many thanks for putting aside time to give all of your beliefs.
2 Trackbacks
[...] I found a great tutorial earlier today that you can check out here: Introduction To Mapkit iPhone OS 2.0 [...]
[...] widmet sich den Grundlagen der SDK-Programmierung und erklärt im zweiten Teil des Artikels “Introduction to MapKit in iPhone OS 3.0” die Implementation der “reverse geocoding”-Funktionalität in die eigene [...]