I'm writing an Application that makes use of MapKit. I have implemented MKLocalSearch and I get back an array of MKMapItem's. However I was wondering if it was possible to get the category of each of these items.For example in the Maps application there is different icons displayed for shops, hotels, train stations and so on. Also if you view a place mark.You get a category label such as Grocery. As a developer can I access that information for a Map Item? If so I would like to know how.
Thank You
Yes you can get this information. See below method for information details from search location.
I fear that you can only get address details from MKPlacemark
.
What now you have to do is, get address details from MKPlacemark
and you need to take a help of any open source API that can help you to categories addresses into some labels/annotation.
One of the good API is Mapbox, but unfortunately it is paid.
So from third party API you can do magical search. I haven't search for kind of API / WebService but it should be there.
Objective C Code:
- (void) searchForPlace:(NSString *) keyWord {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = keyWord; // @"restaurant"
MKCoordinateSpan span = MKCoordinateSpanMake(.1, .1);
CLLocationCoordinate2D location = self.mapView.centerCoordinate;
request.region = MKCoordinateRegionMake(location, span);
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
[search startWithCompletionHandler:
^(MKLocalSearchResponse *response, NSError *error) {
[self.txtSearch setEnabled:YES];
[self removeMapOverlay];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (!error) {
// Result found
@try {
if (response.mapItems && [response.mapItems count] > 0) {
for (MKMapItem *item in response.mapItems) {
MKPlacemark *placeMark = item.placemark;
// Address details
NSDictionary *address = placeMark.addressDictionary;
NSString *titleString = @"";
NSString *subtitleString = @"";
NSString *name = @"";
NSString *Thoroughfare = @"";
NSString *State = @"";
NSString *City = @"";
NSString *Country = @"";
name = [address objectForKey:@"Name"] ? [address objectForKey:@"Name"] : @"";
Thoroughfare = [address objectForKey:@"Thoroughfare"] ? [address objectForKey:@"Thoroughfare"] : @"";
State = [address objectForKey:@"State"] ? [address objectForKey:@"State"] : @"";
City = [address objectForKey:@"City"] ? [address objectForKey:@"City"] : @"";
Country = [address objectForKey:@"Country"] ? [address objectForKey:@"Country"] : @"";
titleString = [NSString stringWithFormat:@"%@ %@", name, Thoroughfare];
subtitleString = [NSString stringWithFormat:@"%@ %@ %@", State, City, Country];
CustomAnnotation *annotation = [[CustomAnnotation alloc] initWithTitle:titleString subTitle:subtitleString detailURL:item.url location:placeMark.location.coordinate];
[self.mapView addAnnotation:annotation];
}
[self mapView:self.mapView regionDidChangeAnimated:YES];
}
}
@catch (NSException *exception) {
NSLog(@"Exception :%@",exception.description);
}
} else {
NSLog(@"No result found.");
}
}];
}
Swift Code:
func searchForPlace(keyword: String) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
var requset = MKLocalSearchRequest()
requset.naturalLanguageQuery = keyword
let span = MKCoordinateSpanMake(0.1, 0.1)
let region = MKCoordinateRegion(center: self.mapView.centerCoordinate, span: span)
var search = MKLocalSearch(request: requset)
search.startWithCompletionHandler { (var response: MKLocalSearchResponse!, var error: NSError!) -> Void in
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
if (error != nil) {
// Result found
if (response.mapItems != nil && response.mapItems.count > 0) {
for item: MKMapItem! in response.mapItems as [MKMapItem] {
var placeMark = item.placemark as MKPlacemark!
// Address details...
var address = placeMark.addressDictionary as NSDictionary!
var titleString: String!
var subtitleString: String!
var name: String!
var Thoroughfare: String!
var State: String!
var City: String!
var Country: String!
var emptyString: String! = " "
name = (address.objectForKey("name") != nil ? address.objectForKey("name") : emptyString) as String
Thoroughfare = (address.objectForKey("Thoroughfare") != nil ? address.objectForKey("Thoroughfare") : emptyString) as String
State = (address.objectForKey("State") != nil ? address.objectForKey("State") : emptyString) as String
City = (address.objectForKey("City") != nil ? address.objectForKey("City") : emptyString) as String
Country = (address.objectForKey("Country") != nil ? address.objectForKey("Country") : emptyString) as String
titleString = String(format: "%@ %@", name, Thoroughfare)
subtitleString = String(format: "%@ %@ %@", State, City, Country)
var customAnnotation = CustomAnnotation(coordinate: placeMark.location.coordinate, title: titleString, subtitle: subtitleString, detailURL: item.url)
self.mapView.addAnnotation(customAnnotation)
}
self.mapView(self.mapView, regionDidChangeAnimated: true)
}
}
}
}
I know this is an old question, but I stumbled upon the same need - getting the category info from a MKMapItem
object.
Q: Can you get category information from a MKMapItem
?
A: Yes this is possible. You can pull this from a map item.
Q: Is this allowed by Apple?
A: Not really... you must use key-values to get these properties, so it technically would be accessing private frameworks. BUT, you didnt ask if it had to be "allowed."
Here's a nice method that I have (it was in Objc but converted it to swift for you, so forgive me if there are any bugs - haven't tested this)
// Let "item" be some MKMapItem
let geo_place = item.value(forKey: "place") as! NSObject
let geo_business = geo_place.value(forKey: "business") as! NSObject
let categories = geo_business.value(forKey: "localizedCategories") as! [AnyObject]
var categoriesList = [Any]()
for geo_cat in categories.first as! [AnyObject] {
let level = geo_cat.value(forKeyPath: "level") as! Int
let geo_loc_name = geo_cat.value(forKeyPath: "localizedNames") as! NSObject
let name = (geo_loc_name.value(forKeyPath: "name") as! [String]).first
categoriesList.append(["level" : NSNumber(value: level), "name" : name as Any])
}
This gives you categories like:
{
level : 1;
name : "Coffee & Tea"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With