"Name" of a CLPlacemark - iphone

I'm trying to understand CLPlacemark and when/how to create information for a callout of a pin that is added to a map. Before what I read in More iOS 3 development a few years ago, they reverse geocoded an address and built the address (street, zip, state, etc). First, do I need to build this string myself? I was trying to find out how to get the name of a location for certain known things like searching for the apple store in the code below:
NSString *address = #"1 stockton, san francisco, ca";
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
[placemarks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"obj description: %#", [obj description]);
CLPlacemark *aPlacemark = (CLPlacemark *)obj;
NSLog(#"%#", [aPlacemark.addressDictionary description]);
NSLog(#"name: %#", ((CLPlacemark *)obj).name);
}];
];
When I print out the description, I see that the Console says:
Apple Store, San Francisco, 1 Stockton St, San Francisco, CA 94108-5805, United States # <+37.78584545,-122.40651752> +/- 100.00m, region (identifier <+37.78584545,-122.40652161> radius 18.96) <+37.78584545,-122.40652161> radius 18.96m
Where does it get the Apple Store, San Francisco, name? I thought it would be the CLPlacemark.name property, but that is null. So in trying to figure out how the name property is created, I found:
NSLog(#"%#", [aPlacemark.addressDictionary description]);
I get the output:
City = "San Francisco";
Country = "United States";
CountryCode = US;
FormattedAddressLines = (
"Apple Store, San Francisco",
"1 Stockton St",
"San Francisco, CA 94108-5805",
"United States"
);
PostCodeExtension = 5805;
State = California;
Street = "1 Stockton St";
SubAdministrativeArea = "San Francisco";
SubLocality = "Union Square";
SubThoroughfare = 1;
Thoroughfare = "Stockton St";
ZIP = 94108;
From this, all I can see is that in the FormattedAddressLines key of the addressDictionary, the title is there as well.
So I guess my 2 questions are:
1) How do I get the name of a location if there is one (i.e. Apple Store)?
2) Do I need to build my string anymore since it seems like the address dictionary does that for me already?
Thanks!

You can use ABCreateStringWithAddressDictionary function from AddressBookUI framework to get the address string from CLPlacemark's "addressDictionary" property.

To answer your first question, use the areasOfInterest property of the CLPlacemark.
As for the second question, thats really up to you, and how you want to format the string. If you want to build it using strings from the addressDictionary property, then by all means do so. You can pick and choose the parts, and create a string all in the completion handler.
Also, you mentioned you want to create an annotation for displaying on a map. I personally subclass MKAnnotation, and use that to quickly create an annotation to display on a map.
MyAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation> {
NSString *_name;
NSString *_address;
CLLocationCoordinate2D _coordinate;
}
#property (copy) NSString *name;
#property (copy) NSString *address;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate;
#end
MyAnnotation.m
#import "MyAnnotation.h"
#implementation MyAnnotation
#synthesize name = _name;
#synthesize address = _address;
#synthesize coordinate = _coordinate;
- (id)initWithName:(NSString*)name address:(NSString*)address coordinate:(CLLocationCoordinate2D)coordinate
{
if ((self = [super init])) {
_name = [name copy];
_address = [address copy];
_coordinate = coordinate;
}
return self;
}
- (NSString *)title
{
return _name;
}
- (NSString *)subtitle
{
return _address;
}
#end
Declare an NSMutableArray to hold all the annotations, and throw the initWithName:address:coordinate: in your completion handler, and you can quickly get an array of annotations you can add to your map.
NSString *address = #"1 stockton, san francisco, ca";
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error)
{
NSMutableArray *annotationArray = [NSMutableArray array];
for (CLPlacemark *aPlacemark in placemarks)
{
NSString *nameString = // Get your name from an array created by aPlacemark.areasOfInterest;
NSString *addressString = // Put your address string info you get from the placemark here.
CLLocationCoordinate2D coordinate = aPlacemark.location.coordinate;
MyAnnotation *annotation = [[MyAnnotation alloc] initWithName:nameString address:addressString coordinate:coordinate];
[annotationArray addObject:annotation];
}
// Now save annotationArray if you want to use it later
// Add it to your MapView with [myMapView addAnnotations:annotationArray];
}];
Hope that helps out!

Related

Get a friendly location name given a set of geo coords?

Is it possible to get a human-friendly textual description of the closest meaningful landmark (such as a street intersection) for a given set of geographical coordinates, for example via a web service like Google Maps or some other third party? I am using MapKit, but I doubt it has anything built in. Turns out it does.
For example, I'm looking for something like the closest street intersection (in fact that would be ideal) or any kind of "place name" really. Things like:
E Hastings St and Main St
128 W Cordova St
PNE Fairgrounds
So I have done a project with this exact problem I came across... You can refer to the CLPlacemark class reference in the apple developer webpage.
Here is the way I used it, I think you also have to add the corelocation library as well to the project, as I had done.
#import <CoreLocation/CoreLocation.h>
Now in the .h file:
Add the CLLocation Delegate : <CLLocationManagerDelegate>
Then add the following instance variables:
CLLocationManager *locationManager;
CLLocation *currentLocation;
Now in the .m file:
-(void) viewDidLoad{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move, location is updated
locationManager.desiredAccuracy = kCLLocationAccuracyBest; // get best current locaton coords
locationManager.headingFilter = 1;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
And now implement the CLLocationManager Delegate Method in after the viewDidLoad method, or before, whichever you perfer:
#pragma mark CLLocationManager Delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
currentLocation = [locations objectAtIndex:0];
[locationManager stopUpdatingLocation];
NSLog(#"Detected Location : %f, %f", currentLocation.coordinate.latitude, currentLocation.coordinate.longitude);
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:currentLocation
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error){
NSLog(#"Geocode failed with error: %#", error);
return;
}
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#"City = %# : State = %# : Country = %# : Zip Code = %#", placemark.locality, placemark.administrativeArea, placemark.ISOcountryCode, placemark.postalCode);
}];
}
Run the code and make sure that if your using the iOS simulator, be sure to simulate a location by clicking on the arrow button just above the console output screen.
It only shows up once you have built and ran your project.
Hopefully this helps you :)
Heres the output I got:
2013-08-02 20:39:46.935 PowerOneApp[3449:c07] Detected Location : 37.785834, -122.406417
2013-08-02 20:39:49.773 PowerOneApp[3449:c07] City = San Francisco : State = California : Country = US : Zip Code = 94115
EDIT
Sorry, I realized when I wrote this answer that you wanted more EXACT coordinates.
Here:
#pragma mark CLLocationManager Delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
currentLocation = [locations objectAtIndex:0];
[locationManager stopUpdatingLocation];
NSLog(#"Detected Location : %f, %f", currentLocation.coordinate.latitude, currentLocation.coordinate.longitude);
CLGeocoder *geocoder = [[CLGeocoder alloc] init] ;
[geocoder reverseGeocodeLocation:currentLocation
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error){
NSLog(#"Geocode failed with error: %#", error);
return;
}
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#"%#", placemark.addressDictionary);
NSLog(#"%#", [placemark.addressDictionary valueForKey:#"Street"]);
}];
}
Heres the output:
2013-08-02 20:44:26.052 PowerOneApp[3531:c07] Detected Location : 37.785834, -122.406417
2013-08-02 20:44:26.340 PowerOneApp[3531:c07] {
City = "San Francisco";
Country = "United States";
CountryCode = US;
FormattedAddressLines = (
"Apple Store, San Francisco",
"1800 Ellis St",
"San Francisco, CA 94115-4004",
"United States"
);
Name = "Apple Store, San Francisco";
PostCodeExtension = 4004;
State = California;
Street = "1800 Ellis St";
SubAdministrativeArea = "San Francisco";
SubLocality = "Union Square";
SubThoroughfare = 1800;
Thoroughfare = "Ellis St";
ZIP = 94115;
}
2013-08-02 20:44:26.340 PowerOneApp[3531:c07] 1800 Ellis St
As you can see, there is a property called addressDictionary that returns ALL the propertys the CLPlacemark class holds. So here, if your familiar with NSDictionary objects, I just outputted the entire dictionary first then specified which value I wanted to log.
Hopefully this helps your exact question :)
check google maps api, I think something like this should work:
var geocoder = new google.maps.Geocoder(),
lat = "12.1234",
long = "98.7654",
latlng = new google.maps.LatLng(sLat, sLong);
geocoder.geocode({"latLng":latlng},function(data,status) {
if(status == google.maps.GeocoderStatus.OK) {
var add = data[1].formatted_address; //this is the full address
alert(add);
}
});
you can get the "E Hastings St and Main St" and full name of venue as well, you just need to add more stuff to the function. check out the google maps api.

Convert NSString Latiude/Longitude Coordinates to City, State, and Timezone with CLGeocoder

I have a view controller that pulls the users latitude and longitude coordinates from the app delegate. This works well, but I also need the user's city, state, and time zone. I know I should use CLGeocoder for this (please see last chunk of code), but don't know how to put it together. I'd just need NSStrings of the city, state, and timezone. Anyone have any pointers or an example? Thank you!
In my App Delegate, I use CCLocationManager to get the Coordinates like this:
- (NSString *)getUserCoordinates
{
NSString *userCoordinates = [NSString stringWithFormat:#"latitude: %f longitude: %f",
locationManager.location.coordinate.latitude,
locationManager.location.coordinate.longitude];
locationManager = [[CLLocationManager alloc] init];
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
return userCoordinates;
}
- (NSString *)getUserLatitude
{
NSString *userLatitude = [NSString stringWithFormat:#"%f",
locationManager.location.coordinate.latitude];
return userLatitude;
}
- (NSString *)getUserLongitude
{
NSString *userLongitude = [NSString stringWithFormat:#"%f",
locationManager.location.coordinate.longitude];
return userLongitude;
}
In my View Controller, I get the user's Latitude and Longitude as an NSString with this:
NSString *userLatitude =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate
getUserLatitude];
NSString *userLongitude =[(PDCAppDelegate *)[UIApplication sharedApplication].delegate
getUserLongitude];
I would like to get the city, state, and timezone. I understand I need CLGeocoder, but can't figure out how to meld it together:
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks,
NSError *error) {
for (CLPlacemark * placemark in placemarks) {
NSString *locality = [placemark locality];
}
}
A couple things, Brandon:
1) CLLocationManager might not give you an instant response to your request for coordinates. You should set your view controller as a CLLocationManager delegate and then when the location update comes in (which will be in the locationManager:didUpdateLocations: method), then you can run your CLGeocoder method.
2)
Which I wrote to look like this:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog( #"didUpdateLocation!");
NSLog( #"latitude is %# and longitude is %#", [self getUserLatitude], [self getUserLongitude]);
CLGeocoder * geoCoder = [[CLGeocoder alloc] init];
[geoCoder reverseGeocodeLocation:locationManager.location completionHandler:^(NSArray *placemarks, NSError *error) {
for (CLPlacemark * placemark in placemarks) {
NSString * addressName = [placemark name];
NSString * city = [placemark locality]; // locality means "city"
NSString * administrativeArea = [placemark administrativeArea]; // which is "state" in the U.S.A.
NSLog( #"name is %# and locality is %# and administrative area is %#", addressName, city, administrativeArea );
}
}];
}
Getting the location's timezone is a bit trickier. I bet there's an API or some sample code to get it within iOS, but it's not a part of the CLPlacemark API.
Form a CLLocation from latitude and longitude double value. Then feed that location to reverseGeocodeLocation:completionHandler:
Also note that the method reverseGeocodeLocation:completionHandler: is asynchronous.
You can also use, CLLocationManagerDelegate's locationManager:didUpdateHeading:
to asynchronously update if there is an Location available, which is better.
Anyway following your approach, just modifying some of your code from AppDelegate
- (double)getUserLatitude
{
return retrun locationManager.location.coordinate.latitude;
}
- (double)getUserLongitude
{
retrun locationManager.location.coordinate.longitude;
}
-(CLLocationManager*) getLocationManager
{
return locationManager;
}
Now Form a Location object
double latt = [(PDCAppDelegate *)[UIApplication sharedApplication].delegate getUserLatitude];
double longt = [(PDCAppDelegate *)[UIApplication sharedApplication].delegate getUserLongitude];
CLLocation loc = [[CLLocation alloc] initWithLatitude:latt longitude:longt]
or you can directly get the location object from CLLocationManager
CLLocation loc = [(PDCAppDelegate *)[UIApplication sharedApplication].delegate getLocationManager].location;
Then you can use your code feeding the location to reverseGeocodeLocation:completionHandler: and Get the CLPlaceMark
[geoCoder reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks,
NSError *error) {
for (CLPlacemark * placemark in placemarks) {
NSString *locality = [placemark locality];
NSString * name = [placemark name];
NSString *country = [placemark country];
/*you can put these values in some member vairables*/
m_locality = [placemark locality];
m_name = [placemark name];
m_country = [placemark country];
}
}
While I don't have a solution for the timezone issue (I agree with others who've answered this question - look for a non-Apple API), I thought I'd provide an answer in Swift, for those who are curious:
func provideGeocodedStringForLocation(location: CLLocation, withCompletionHandler completionHandler: (String) -> ()) {
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { (placemarks: [CLPlacemark]?, error: NSError?) -> Void in
guard let placemarks = placemarks where placemarks.count > 0 && error == nil else {
if let error = error { print(error.localizedDescription) }
completionHandler("Earth")
return
}
let city = placemarks[0].locality ?? ""
let state: String
if let adminArea = placemarks[0].administrativeArea {
state = ", \(adminArea)"
} else {
state = ""
}
completionHandler("\(city)\(state)") // produces output similar to "Boulder, CO"
}
}
// get the lat/long from your UIAppDelegate subclass
let latitude = CLLocationDegrees("40.0176")
let longitude = CLLocationDegrees("-105.28212")
let location = CLLocation(latitude: latitude, longitude: longitude)
provideGeocodedStringForLocation(location) { print($0) }
I got timezone name from placemark description. And it works for ios 8 and higher.
You can check this link for how to get time zone

CLPlacemark - State Abbreviations?

I was wondering if it was possible to get the state abbreviations from CLPlacemark?
In the CLPlacemark Reference from Apple it states:
administrativeArea
The state or province associated with the placemark. (read-only)
#property(nonatomic, readonly) NSString *administrativeArea
Discussion
If the placemark location is Apple’s headquarters, for example, the value for this property would be the string “CA” or “California”.
but whenever I use it, I only get the full state (i.e California) and not the abbreviation (i.e CA). Can anyone help me here?
For anyone else that needs a solution for this, I've created a category class for CLPlacemark that returns the short state string. All you need to do is call myPlacemark shortState
CLPlacemark+ShortState.h
#import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h>
#interface CLPlacemark (ShortState)
- (NSString *)shortState;
#end
CLPlacemark+ShortState.m
#import "CLPlacemark+ShortState.h"
#interface CLPlacemark (ShortStatePrivate)
- (NSDictionary *)nameAbbreviations;
#end
#implementation CLPlacemark (ShortState)
- (NSString *)shortState {
NSString *state = [self.administrativeArea lowercaseString];
if (state.length==0)
return nil;
return [[self nameAbbreviations] objectForKey:state];
}
- (NSDictionary *)nameAbbreviations {
static NSDictionary *nameAbbreviations = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
nameAbbreviations = [NSDictionary dictionaryWithObjectsAndKeys:
#"AL",#"alabama",
#"AK",#"alaska",
#"AZ",#"arizona",
#"AR",#"arkansas",
#"CA",#"california",
#"CO",#"colorado",
#"CT",#"connecticut",
#"DE",#"delaware",
#"DC",#"district of columbia",
#"FL",#"florida",
#"GA",#"georgia",
#"HI",#"hawaii",
#"ID",#"idaho",
#"IL",#"illinois",
#"IN",#"indiana",
#"IA",#"iowa",
#"KS",#"kansas",
#"KY",#"kentucky",
#"LA",#"louisiana",
#"ME",#"maine",
#"MD",#"maryland",
#"MA",#"massachusetts",
#"MI",#"michigan",
#"MN",#"minnesota",
#"MS",#"mississippi",
#"MO",#"missouri",
#"MT",#"montana",
#"NE",#"nebraska",
#"NV",#"nevada",
#"NH",#"new hampshire",
#"NJ",#"new jersey",
#"NM",#"new mexico",
#"NY",#"new york",
#"NC",#"north carolina",
#"ND",#"north dakota",
#"OH",#"ohio",
#"OK",#"oklahoma",
#"OR",#"oregon",
#"PA",#"pennsylvania",
#"RI",#"rhode island",
#"SC",#"south carolina",
#"SD",#"south dakota",
#"TN",#"tennessee",
#"TX",#"texas",
#"UT",#"utah",
#"VT",#"vermont",
#"VA",#"virginia",
#"WA",#"washington",
#"WV",#"west virginia",
#"WI",#"wisconsin",
#"WY",#"wyoming",
nil];
});
return nameAbbreviations;
}
#end
I think you can't get the abbreviations of the states but you can make your own class for this..
List all the states(states are standards)
compare those states and return the abbreviation
Code..
Class StateAbbreviation
StateAbbreviation.h
#interface StateAbbreviation : NSString {
}
+ (NSString *)allStates:(int)index;
+ (NSString *)abbreviatedState:(NSString *)strState;
#end
StateAbbreviation.m
#implementation StateAbbreviation
+ (NSString *)allStates:(NSString *)strState {
// Remove all space on the string
strState = [strState stringByReplacingOccurrencesOfString:#" " withString:#""];
//Sample states
NSArray *states = [[NSArray alloc] initWithObjects:
#"ALABAMA",
#"ALASKA", //AK
#"AMERICANSAMOA", //AS
#"ARIZONA", //AZ
#"ARKANSAS", //AR
#"CALIFORNIA", //CA
nil];
NSUInteger n = [states indexOfObject:strState];
if (n > [states count] - 1) {
strAbbreviation = #"NOSTATE";
}
else {
strAbbreviation =[self abbreviatedState:n];
}
[states release];
return strAbbreviation;
}
+ (NSString *)abbreviatedState:(int)index {
NSArray *states = [[NSArray alloc] initWithObjects:
#"AL",
#"AK",
#"AS",
#"AZ",
#"AR",
#"CA",
nil];
NSString *strAbbreviation = [states objectAtIndex:index];
[states release];
return strAbbreviation;
}
#end
When you call the class it should be something like this
NSString *upperCase = [#"California" uppercaseString]; // California could be from (NSString *)placemark.administrativeArea;
NSString *abbr = [StateAbbreviation allStates:upperCase];
NSLog(#"%#", abbr); // Result should be CA
This are only samples you can research all states something like this, states and their abbreviations also like this states and their abbreviations
I believe the documentation is just incorrect. The administrativeArea is always going to return the full state name for places in the United States. To get the state abbreviation you'll most likely have to create a dictionary look up table so that searching for the key "California" will return you the value "CA".
Here is another category using FormattedAddressLines, it returns a result like California, CA
-(NSString *) stateWithAbbreviation {
if ([[self.addressDictionary objectForKey:#"CountryCode"] isEqualToString:#"US"] && self.addressDictionary) {
NSDictionary *addressLines = [self.addressDictionary objectForKey:#"FormattedAddressLines"];
for (NSString* addressLine in addressLines) {
NSRange stateRange = [addressLine rangeOfString:self.postalCode options:NSCaseInsensitiveSearch];
if (stateRange.length > 0) {
NSRange lastSpace = [addressLine rangeOfString:#" " options:NSBackwardsSearch];
if (lastSpace.length > 0) {
NSString *state = [[addressLine substringToIndex:lastSpace.location] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
lastSpace = [state rangeOfString:#" " options:NSBackwardsSearch];
if (lastSpace.length > 0) {
NSString *abbr = [[state substringFromIndex:lastSpace.location] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
return [NSString stringWithFormat:#"%#, %#", self.administrativeArea, abbr];
}
}
}
}
}
return self.administrativeArea;
}
Not perfect but it works as long as Apple changes the format of the address lines I think.
For people who need the state list with objects and keys swapped (e.g. on iOS 7 I get "CA" from placemark.administrativeArea):
NSDictionary *nameAbbreviations = [NSDictionary dictionaryWithObjectsAndKeys:
#"alabama",#"AL",
#"alaska",#"AK",
#"arizona",#"AZ",
#"arkansas",#"AR",
#"california",#"CA",
#"colorado",#"CO",
#"connecticut",#"CT",
#"delaware",#"DE",
#"district of columbia",#"DC",
#"florida",#"FL",
#"georgia",#"GA",
#"hawaii",#"HI",
#"idaho",#"ID",
#"illinois",#"IL",
#"indiana",#"IN",
#"iowa",#"IA",
#"kansas",#"KS",
#"kentucky",#"KY",
#"louisiana",#"LA",
#"maine",#"ME",
#"maryland",#"MD",
#"massachusetts",#"MA",
#"michigan",#"MI",
#"minnesota",#"MN",
#"mississippi",#"MS",
#"missouri",#"MO",
#"montana",#"MT",
#"nebraska",#"NE",
#"nevada",#"NV",
#"new hampshire",#"NH",
#"new jersey",#"NJ",
#"new mexico",#"NM",
#"new york",#"NY",
#"north carolina",#"NC",
#"north dakota",#"ND",
#"ohio",#"OH",
#"oklahoma",#"OK",
#"oregon",#"OR",
#"pennsylvania",#"PA",
#"rhode island",#"RI",
#"south carolina",#"SC",
#"south dakota",#"SD",
#"tennessee",#"TN",
#"texas",#"TX",
#"utah",#"UT",
#"vermont",#"VT",
#"virginia",#"VA",
#"washington",#"WA",
#"west virginia",#"WV",
#"wisconsin",#"WI",
#"wyoming",#"WY",
nil];
As of at least iOS 8, CLPlacemark's administrativeArea returns a two-letter abbreviation for US States.
You don't need to extend CLPlacemark with a category like the one in the accepted answer as long as you're targeting iOS 8 and newer (which you should be by now).
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:#"1 Infinite Loop, Cupertino, CA" completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks firstObject];
NSLog(#"State: %#", placemark.administrativeArea);
}];
Run this and you'll get:
State: CA
SWIFT variant of dictionary
let states = [
"AL":"alabama",
"AK":"alaska",
"AZ":"arizona",
"AR":"arkansas",
"CA":"california",
"CO":"colorado",
"CT":"connecticut",
"DE":"delaware",
"DC":"district of columbia",
"FL":"florida",
"GA":"georgia",
"HI":"hawaii",
"ID":"idaho",
"IL":"illinois",
"IN":"indiana",
"IA":"iowa",
"KS":"kansas",
"KY":"kentucky",
"LA":"louisiana",
"ME":"maine",
"MD":"maryland",
"MA":"massachusetts",
"MI":"michigan",
"MN":"minnesota",
"MS":"mississippi",
"MO":"missouri",
"MT":"montana",
"NE":"nebraska",
"NV":"nevada",
"NH":"new hampshire",
"NJ":"new jersey",
"NM":"new mexico",
"NY":"new york",
"NC":"north carolina",
"ND":"north dakota",
"OH":"ohio",
"OK":"oklahoma",
"OR":"oregon",
"PA":"pennsylvania",
"RI":"rhode island",
"SC":"south carolina",
"SD":"south dakota",
"TN":"tennessee",
"TX":"texas",
"UT":"utah",
"VT":"vermont",
"VA":"virginia",
"WA":"washington",
"WV":"west virginia",
"WI":"wisconsin",
"WY":"wyoming"
]

reverse geocoding and localization

I use this code to set a label with a location string
locationString = [[NSString alloc] initWithFormat:#"%#%# - %# %#%#",
thoroughfare,subThoroughfare,postalCode,
locality,countryCode];
locationLabel.text = locationString;
where thoroughfare, subThoroughfare, postalCode, locality,countryCode are obtained from a placemark.
Now, I'd like to visualize this string according the current locale. Have I specify a string format for each locale in which I'm interested or there is a simpler way to obtain this?
Thanks,
Fran
you can use following function
-(void) setLocation:(NSString *)latitude withLongitude:(NSString *)longitude {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *location = [[CLLocation alloc] initWithLatitude:[latitude doubleValue] longitude:
longitude doubleValue]];
CLGeocodeCompletionHandler completionHandler = ^ (NSArray *placemarks, NSError *error){
if (error){
NSLog(#"error in fetching location <%#>",error);
return ;
}
if ( placemarks && placemarks.count >0){
CLPlacemark *mark = [placemarks objectAtIndex:0];
NSString *addresstring = [[mark addressDictionary] objectForKey:#"FormattedAddressLines"] componentsJoinedByString:#","];
*//fetched addressDictionary for key FormattedAddressLines*
}
The addressDictionary property of the placemark object should resolve in part the problem with its FormattedAddressLines array.

How to get a description for each pin, in Google Maps for the iPhone

I have a problem with MKPointAnnotation. I want to create my iPhone application like this:
Show a pin in Google Maps
Show a description on each pin, pulling that description from a NSMutableArray.
So, My question is, how do I show a description on each pin?
This is my code:
NSMutableArray *points = [[NSMutableArray alloc] init];
for(int i=0; i < [dataTable count]; i++) {
MKPointAnnotation *point =[[MKPointAnnotation alloc] init];
CLLocationCoordinate2D coordinate;
coordinate.latitude = [[[dataTable objectAtIndex:i] objectForKey:#"latitude"] floatValue];
coordinate.longitude = [[[dataTable objectAtIndex:i] objectForKey:#"longitude"] floatValue];
[point setCoordinate:coordinate];
[point setTitle:[[dataTable objectAtIndex:i] objectForKey:#"name"]]; //-- name of pin
[points addObject:point];
}
[map addAnnotations:points];
I would adopt the MKAnnotation protocol in my own class and simply override the
- (NSString) title
and implement
- (CLLocationCoordinate2D) coordinate {
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = self.latitude;
theCoordinate.longitude = self.longitude;
return theCoordinate;
}
My class would also have an initialiser that takes all the data it needs (from the array you mentioned)
- (id) initWithTitle:(NSString *)title_ andLatitude:(CLLocationDegrees)latitude_ andLongitude:(CLLocationDegrees)longitude_;
When iterating I would create my own objects and then add them to the collection of annotations.
Cheers...