Reputation: 10744
Below are two examples of strings separated by comma that I get back as results:
NSString *placeResult = @"111 Main Street, Cupertino, CA"
or sometimes the result contains the name of a place:
NSString *placeResult = @"Starbucks, 222 Main Street, Cupertino, CA"
What's the best way to check the strings above to see if it starts with a name or or a street address?
If it does start with a name (i.e. Starbucks in the 2nd example above"), I'd like to extract the name and store it into another variable. Thus after extraction the string will be:
NSLog (@"%s", placeResult);
The log will print:
"222 Main Street, Cupertino, CA"
Another string will now store the @"Starbucks" in it:
NSLog (@"%s", placeName);
The log will print:
"Starbucks"
Important: I can't lose the comma separations after extraction.
Thank you!
Upvotes: 0
Views: 1580
Reputation: 318814
Make use of NSDataDetector
and NSTextCheckingResult
:
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeAddress error:nil];
NSString *str = @"Starbucks, 222 Main Street, Cupertino, CA";
NSArray *matches = [detector matchesInString:str options:0 range:NSMakeRange(0, str.length)];
for (NSTextCheckingResult *match in matches) {
if (match.resultType == NSTextCheckingTypeAddress) {
NSDictionary *data = [match addressComponents];
NSLog(@"address = %@, range: %@", data, NSStringFromRange(match.range));
NSString *name = data[NSTextCheckingNameKey];
if (!name && match.range.location > 0) {
name = [str substringToIndex:match.range.location - 1];
// "name" may now include a trailing comma and space - strip these as needed
}
}
}
This outputs:
address = {
City = Cupertino;
State = CA;
Street = "222 Main Street";
}, range: {11, 30}
The odd thing is that the resulting dictionary of results does not contain a reference to the "Starbucks" portion. What you can do is check to see of the addressComponents
contains a value for the NSTextCheckingNameKey
. If not, check the range of the match. If the match's range isn't the start of the string, then you can use that value to extract the name from the beginning of the string.
Upvotes: 5
Reputation: 100632
To get an array of the things between commas, you could use:
NSArray *components = [placeResult componentsSeparatedByString:@","];
Possibly with a follow-up of:
NSMutableArray *trimmedComponents =
[NSMutableArray arrayWithCapacity:[components count]];
NSCharacterSet *whitespaceCharacterSet = [NSCharacterSet whitespaceCharacterSet];
for(NSString *component in components)
[trimmedComponents addObject:
[component stringByTrimmingCharactersInSet:whitespaceCharacterSet]];
To remove any leading or trailing spaces from each individual component. You would reverse the transformation using e.g.
NSString *fullAddress = [trimmedComponents componentsJoinedByString:@", "];
So then the question is, given NSString *firstComponent = [trimmedComponents objectAtIndex:0];
, how do you guess whether it is a name or a street address? If it's as simple as checking whether there's a number at the front that isn't zero then you can just do:
if([firstComponent integerValue])
{
/* ... started with a non-zero number ... */
NSString *trimmedAddress = [[trimmedComponents subArrayWithRange:
NSMakeRange(1, [trimmedComponents count]-1)] componentsJoinedByString:", "];
NSLog(@"trimmed address is: %@");
}
Though that conditional test would also have worked with placeResult
, and you'll probably want to add validity checks to make sure you have at least two components before you start assuming you can make an array from the 2nd one onwards.
Upvotes: 2