XCode : using MapKit with no geocoding available out of the box

xcode

One of the tasks in the CSCW lab was to create a map on which the users to see the location of a specific address.

So I started working on it, knowing that the newest framework brings a lot of goodies, through which there is also a map framework. But surprise! Apple provides only reverse geocoding, not forward geocoding. This means that you can only transform a pair of Latitude / Longitude to the Map and it will show it to the user. But what to do when user enters an address?

My point is that nobody caries with him a GPS to search for the address, get the coordinates and enter them into my map!

I was curious about it and after a little search I found that there was a big argue about the geocoding and Apple didn’t want to pay the price that Google and Tom-Tom asked for this feature.

So I pursue in searching how to integrate geocoding into my application using free end-user services,like Google maps, Yahoo maps and other services alike. I finally settled to Yahoo because it was a RESTful service – requiring just a URL composed on some basic rules.

First, lets us set some helper variables :

//the latitude and longitude as strings
NSString *Latitude, *Longitude;

//the parser state - required because we need to know what above variable to fill
NSString *State;

Composing the URL is quite simple, it requires only to change YOUR_APPID with your one, obtained from Yahoo:

NSString *strTemp = [[strTemp stringByReplacingOccurrencesOfString:@"," withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@"+"];
NSString *URL = [NSString stringWithFormat: @"http://local.yahooapis.com/MapsService/V1/geocode?appid=YOUR_APPID&location=%@",
						   strTemp];
	
NSURL* url = [NSURL URLWithString:URL];
// fill the parser with the contens of the reply
NSXMLParser* parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];

State = @"";

// Parser, get to work!
[parser parse];

//here the code returns from parsing and you can use the Longitude and Latitude variables already set

The result of the query for Schloss Birlinghoven (the location of Fraunhofer FIT) looks like this:

<resultset xsi:schemalocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd">
    <result precision="street">
        <latitude>50.748930</latitude>
        <longitude>7.221640</longitude>
        <address>Schlossstrasse</address>
        <city>53757 Sankt Augustin</city>
        <state>Germany</state>
        <zip />
        <country>DE</country>
    </result>
</resultset>

And the parser methods, required because you need to handle the delegated events of NSXMLParser:

#pragma mark -

#pragma mark Parser delegates


- (void) parser:(NSXMLParser *)parser 
didStartElement:(NSString *)elementName
   namespaceURI:(NSString *)namespaceURI
  qualifiedName:(NSString *)qualifiedName
	attributes:(NSDictionary *)attributeDict
{
	State = @"";

	if ( [elementName isEqualToString:@"Latitude"] )
 		State = @"1";

	if ( [elementName isEqualToString:@"Longitude"]) 
		State = @"2";
}



- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
	if ( [State isEqualToString:@"1"] ) Latitude = string;
	if ( [State isEqualToString:@"2"] ) Longitude = string;
}

 

Enjoy!