I have three type of string and i want to format that string to get street number, street name, city name.
The first type is : 34 Ellis Street, San Francisco
Here i want to make it like
street number : 34
street name : Ellis Street
city name : San Francisco
The second type is : 4FL, 800 Market Street, San Francisco
Here i want to delete 4FL,
And i want to make it like
street number : 800
street name : Market Street
city name : San Francisco
The third type is : Ellis & Market, San Francisco
Here i want to make it like
street number :
street name : Ellis & Market
city name : San Francisco
How can i do this or any link that show string formatting like this than please suggest.And yes the string i write here is just a format of string i get,string will be changed every time.
The address string is passed to this method and then it is converted into an array having 3 string objects containing streetNumber, streetName and cityName. Then the array is returned to the caller.
-(NSArray *)brakeAddress:(NSString *)address{
NSMutableArray *arr=[NSMutableArray arrayWithArray:[address componentsSeparatedByString:#","]];
if (arr.count>2) {
[arr removeObjectAtIndex:0];
}
NSInteger streetNameInd=[arr count]-2, cityNameInd=[arr count]-1;
NSMutableArray *streetNameArray=[NSMutableArray arrayWithObjects:arr[0], nil];
if ([arr[streetNameInd] intValue]) {
streetNameArray=[NSMutableArray arrayWithArray:([arr[streetNameInd] componentsSeparatedByString:#" "])];
[streetNameArray removeObjectAtIndex:0];
if ([streetNameArray[0] intValue] ==[arr[streetNameInd] intValue]) {
[streetNameArray removeObjectAtIndex:0];
}
}
NSString *streetName=[streetNameArray componentsJoinedByString:#" "];
NSString *streetNumber=#"";
if ([arr[streetNameInd] intValue]!=0) {
streetNumber=[NSString stringWithFormat:#"%d", [arr[streetNameInd] intValue]];
}
NSString *city=arr[cityNameInd];
// NSLog(#"\nstreet number :%#\nstreet name :%#\ncity name :%#",streetNumber, streetName,city);
NSArray *addressParts=[NSArray arrayWithObjects:streetNumber, streetName, city, nil];
return addressParts;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
NSString *str1=#"34 Ellis Street, San Francisco";
NSString *str2=#"4FL, 800 Market Street, San Francisco";
NSString *str3=#"Ellis & Market, San Francisco";
NSArray *firstAddress=[self brakeAddress:str1];
NSArray *secondAddress=[self brakeAddress:str2];
NSArray *thirdAddress=[self brakeAddress:str3];
NSLog(#"\n1st : street number :%#\nstreet name :%#\ncity name :%#",firstAddress[0],firstAddress[1],firstAddress[2]);
NSLog(#"\n2nd : street number :%#\nstreet name :%#\ncity name :%#",secondAddress[0],secondAddress[1],secondAddress[2]);
NSLog(#"\n3rd : street number :%#\nstreet name :%#\ncity name :%#",thirdAddress[0],thirdAddress[1],thirdAddress[2]);
}
1) Separate with:
NSArray *arrayOfComponents = [yourString componentsSeparatedByString:#","];
2) The last component will always be your city name
3) Then check the (Last - 1) component with
NSArray *array = [yourString componentsSeparatedByString:#" "];
2) Take the FIRST element of the array and use this
NSCharacterSet* notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
// newString consists only of the digits 0 through 9
}
3) If it has only digits then, the FIRST element is your street number, and just make a new string by appending the remaining elements to get the street name. Else the past (last -1) from the previous array is the street name.
This is the basic idea, the logic can obviously be improved.
Edit: since you mentioned that this string is provided by google api it means you are probably getting a JSON response. You should use the complete JSON response to get your textfields filled. There is a JSON to NSDictionary Class you can use:see here
May be first you can implement code to break the address string into different variables such as _streetNum,_streetName,_cityName then you can use following code line for formatting the string
NSString* formattedString = [[NSString alloc] initWithFormat:#"street number : %#\nstreet name :%#\ncity name :%#",_streetNum,_streetName,_cityName];
Try this:
NSArray *array = [yourString componentsSeparatedByString:#" "];
It will give you an array wsth all strings separated by " ";
Try in the following way and parse the response whatever you need related to that address
http://maps.googleapis.com/maps/api/geocode/json?address=34%20Ellis%20Street,%20San%20Francisco,+CA&sensor=true
HOpe it may help you.
You need to use Regular Expressions. Have a look at this: Regular Expressions
Here is a piece of code that might help you.
NSString *addressString;
NSArray *tempArray = [addressString componentsSeparatedByString:#", "];
if([tempArray count]==3){
city = [tempArray objectAtIndex:2];
NSString *tempString = [tempArray objectAtIndex:1];
NSArray *temp1Array = [tempString componentsSeparatedByString:#" "];
if ([temp1Array count]>1) {
st_num = [tempArray objectAtIndex:0];
st_name = [tempString stringByReplacingOccurrencesOfString:
[NSString stringWithFormat:#"%# ",st_num] withString:#""];
}
}
You can extend its logic for your requirement.
I have array of country names and i want to get coordinates of them and store into another array. after this function my longitudes and latitudes arrays are remains still empty. do you have idea what is problem here ? i can't understand.
My Code is :
- (void)geocode {
NSString *strcountry=[[NSString alloc]init];
countryLati=[[NSMutableArray alloc]init];
countryLongi=[[NSMutableArray alloc]init];
countryName =[NSMutableArray arrayWithObjects:#"Bahrain",#"Bangladesh",#"Bhutan",#"China",#"Georgia",#"Hong Kong",nil ];
int count=[countryName count];
for(int i=0;i<count;i++)
{
strcountry=[countryName objectAtIndex:i];
[SVGeocoder geocode:strcountry
completion:^(NSArray *placemarks, NSHTTPURLResponse *urlResponse, NSError *error) {
//NSLog(#"placemarks = %#", placemarks);
CLPlacemark *place = [placemarks objectAtIndex:0];
CLLocation *location = place.location;
CLLocationCoordinate2D coord = location.coordinate;
NSString *tempLati=[[NSString alloc]initWithFormat:#"%g",coord.latitude];
NSString *tempLongi=[[NSString alloc]initWithFormat:#"%g",coord.longitude];
NSLog(#"-------------------------");
NSLog(#"Country : %#",strcountry);
NSLog(#"Latitude : %# ",tempLati);
NSLog(#"Longitude : %# ",tempLongi);
[countryLati addObject:tempLati];
[countryLongi addObject:tempLongi];
}];
}
NSLog(#"%d",[countryName count]);
NSLog(#"%d ",[countryLati count]);
NSLog(#"%d ",[countryLongi count]);
}
I accept Nuzhat Zari solution. Below is the code without using blocks and 3rd party Libraries. Its just a suggetion and showing you one more way of getting location details.
https://developers.google.com/maps/documentation/geocoding/
this URL has a good documentation for Google API.
- (void)geocode
{
NSString *strcountry=[[NSString alloc]init];
countryLati=[[NSMutableArray alloc]init];
countryLongi=[[NSMutableArray alloc]init];
countryName =[NSMutableArray arrayWithObjects:#"Bahrain",#"Bangladesh",#"Bhutan",#"China",#"Georgia",#"Hong Kong",nil ];
int count=[countryName count];
for(int i=0;i<count;i++)
{
strcountry=[countryName objectAtIndex:i];
NSString *urlString = [NSString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#&output=csv", strCountry];
NSString* webStringURL = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:webStringURL];
NSString *locationString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSLog(#"Location String = %#", locationString);
NSArray *receivedGoogleData = [[NSArray alloc] initWithArray:[locationString componentsSeparatedByString:#","]];
searchTermLocation = [[CLLocation alloc] initWithLatitude:[[receivedGoogleData objectAtIndex:2] doubleValue] longitude:[[receivedGoogleData objectAtIndex:3] doubleValue]];
[countryLati addObject:[[receivedGoogleData objectAtIndex:2] doubleValue]];
[countryLongi addObject:[[receivedGoogleData objectAtIndex:3] doubleValue]];
}
NSLog(#"%d",[countryName count]);
NSLog(#"%d ",[countryLati count]);
NSLog(#"%d ",[countryLongi count]);
}
#Mahesh Dhapa : Try this one, From my perspective, I feel this is easy than your way of SVGeoCoder, because no need to extra importing of SVGeocoder classes. BTW, SVGeocoder is simple. But, This is also straight forward without using 3rd party libraries.
You get response from Google like this
200,1,23.8954,34.5478
In which,
200 - Success
1 - Accuracy
23.8954 - Latitude of location
34.5478 - Longitude of location
You can also get this in JSON and XML Format with extra clear information, But you need to decode them to Dictionary from JSON and XML format to use them.
Example JSON Format :
{
"name": "Bahrain",
"Status": {
"code": 200,
"request": "geocode"
},
"Placemark": [ {
"id": "p1",
"address": "Bahrain",
"AddressDetails": {
"Accuracy" : 1,
"Country" : {
"CountryName" : "Bahrain",
"CountryNameCode" : "BH"
}
},
"ExtendedData": {
"LatLonBox": {
"north": 26.3240565,
"south": 25.5798401,
"east": 50.8228639,
"west": 50.3781509
}
},
"Point": {
"coordinates": [ 50.5577000, 26.0667000, 0 ]
}
} ]
}
Example XML Response :
<kml xmlns="http://earth.google.com/kml/2.0">
<Response>
<name>Bahrain</name>
<Status>
<code>200</code>
<request>geocode</request>
</Status>
<Placemark id="p1">
<address>Bahrain</address>
<AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" Accuracy="1">
<Country>
<CountryNameCode>BH</CountryNameCode>
<CountryName>Bahrain</CountryName>
</Country>
</AddressDetails>
<ExtendedData>
<LatLonBox north="26.3240565" south="25.5798401" east="50.8228639" west="50.3781509"/>
</ExtendedData>
<Point>
<coordinates>50.5577000,26.0667000,0</coordinates>
</Point>
</Placemark>
</Response>
</kml>
I think when you want to change local variable in block you need to declare it as block, as follows:
NSArray *stringsArray = #[ #"string 1",
#"String 21",
#"string 12",
#"String 11",
#"Strîng 21",
#"Striñg 21",
#"String 02" ];
NSLocale *currentLocale = [NSLocale currentLocale];
__block NSUInteger orderedSameCount = 0;
NSArray *diacriticInsensitiveSortArray = [stringsArray sortedArrayUsingComparator:^(id string1, id string2) {
NSRange string1Range = NSMakeRange(0, [string1 length]);
NSComparisonResult comparisonResult = [string1 compare:string2 options:NSDiacriticInsensitiveSearch range:string1Range locale:currentLocale];
if (comparisonResult == NSOrderedSame) {
orderedSameCount++;
}
return comparisonResult;
}];
NSLog(#"diacriticInsensitiveSortArray: %#", diacriticInsensitiveSortArray);
NSLog(#"orderedSameCount: %d", orderedSameCount);
Edit:A statement from reference.
A powerful feature of blocks is that they can modify variables in the
same lexical scope. You signal that a block can modify a variable
using the __block storage type modifier.
So you should declare countryLati and countryLongi as block storage.
I am googling NSSting manipulation methods from last few hours. and found many on stack overflow like this here
I have a String "1800 Ellis St, San Francisco, CA 94102, USA". String may have any number of "," . I have to take the third last(San Franncisco) and last(USA) substring after ",".
and output should be "San Franncisco USA".
I have logic how to do this in my mind that but I am struggling to implement it.
I try this code for getting the position of last three "," in string. but it's not work for me
NSInteger commaArr[3];
int index=0;
int commaCount=0;
for(unsigned int i = [strGetCityName length]; i > 0; i--)
{
if([strGetCityName characterAtIndex:i] == ',')
{
commaArr[index]=i;
index++;
++commaCount;
if(commaCount == 3)
{
break;
}
}
}
Thanks
You can do it like this:
NSString *s = #"1800 Ellis St, San Francisco, CA 94102, USA";
NSArray *parts = [s componentsSeparatedByString:#","];
NSUInteger len = [parts count];
NSString *res;
if (len >= 3) {
res = [NSString stringWithFormat:#"%#%#", [parts objectAtIndex:len-3], [parts objectAtIndex:len-1]];
} else {
res = #"ERROR: Not enough parts!";
}
The componentsSeparatedByString: will split the string at ,, and stringWithFormat: will put the parts back together.
NSString *s = #"1800 Ellis St, San Francisco, CA 94102, USA";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"^(?:[^,]*,)?\\s*([^,]*),\\s*(?:[^,]*),\\s*([^,]*)$" options:0 error:NULL];
NSString *result = [regex stringByReplacingMatchesInString:s options:0 range:NSMakeRange(0, [s length]) withTemplate:#"'$1 $2'"];
Try this:
NSString *string = #"1800 Ellis St, San Francisco, CA 94102, USA";
NSArray *components = [string componentsSeparatedByString:#","];
NSString *sanFrancisco = [components objectAtIndex:components.count - 3];
NSString *usa = [components objectAtIndex:components.count - 1];
NSString *result = [sanFrancisco stringByAppendingString:usa];
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"
]