I was wondering if it was possible to get the state abbreviations from CLPlacemark?
In the CLPlacemark Reference from Apple it states:
administrativeArea The sta
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".
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
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"
]
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
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.