How to draw routes on maps in ios 6? - iphone

I want to show maps & draw routes on maps. My application supports for ios 4 plus. So how should i use maps to work on ios 6 as well as before. Also i want to know sholud i use custom mapview in my app to display maps & routes or should i use
[[UIApplication sharedApplication] openURL:]
I have never user MapKits. So please provide if any tutorial. Also let me know if there are any rd party libraries that can be used.

If you don't want an in-app map. Use the following:
NSString *destinationAddress = #"Amsterdam";
Class itemClass = [MKMapItem class];
if (itemClass && [itemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:destinationAddress completionHandler:^(NSArray *placemarks, NSError *error) {
if([placemarks count] > 0) {
MKPlacemark *placeMark = [[MKPlacemark alloc] initWithPlacemark:[placemarks objectAtIndex:0]];
MKMapItem *mapItem = [[MKMapItem alloc]initWithPlacemark:placeMark];
MKMapItem *mapItem2 = [MKMapItem mapItemForCurrentLocation];
NSArray *mapItems = #[mapItem, mapItem2];
NSDictionary *options = #{
MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsMapTypeKey:
[NSNumber numberWithInteger:MKMapTypeStandard],
MKLaunchOptionsShowsTrafficKey:#YES
};
[MKMapItem openMapsWithItems:mapItems launchOptions:options];
} else {
//error nothing found
}
}];
return;
} else {
NSString *sourceAddress = [LocalizedCurrentLocation currentLocationStringForCurrentLanguage];
NSString *urlToOpen = [NSString stringWithFormat:#"http://maps.google.com/maps?saddr=%#&daddr=%#",
[sourceAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
[destinationAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlToOpen]];
}
This opens the map application and checks if it is ios5 or ios6.
For ios5 I use the LocalizedCurrentLocation from this post http://www.martip.net/blog/localized-current-location-string-for-iphone-apps
For ios6 I use the CLGeocoder to get the placemark and then open the map with it and the current location.
Remember to add CoreLocation.framework and MapKit.framework

I think this'll help you:
http://developer.decarta.com/Apis/IOS/Tutorial/Lesson6
http://developer.decarta.com/Apis/IOS/Tutorial/Lesson6Example
Or this?
http://spitzkoff.com/craig/?p=136
Maybe this is fun to do if you want data in your map:
http://www.raywenderlich.com/21365/introduction-to-mapkit-in-ios-6-tutorial
Or some basic information about Mapkit
http://www.techotopia.com/index.php/Working_with_Maps_on_the_iPhone_with_MapKit_and_the_MKMapView_Class

Related

Search nearby in iOS Maps

I am trying to build a simple application using MapKit that will automatically search for a specific place when the app launches and drop pin(s) on the map at the locations(s). I am seeing all sorts of ways to load locations (lat/lon, etc), but nothing that lets me search for a specific business name, restaurant name, etc.
I am expecting to work with Apple Maps. However, if Google Maps would be a better solve than so be it.
Any help would be appreciated. Thanks
iOS >= 6.1 provides MKLocalSearch, MKLocalSearchRequest to search for natural language points of interest. Sample
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.region = regionToSearchIn;
request.naturalLanguageQuery = #"restaurants"; // or business name
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
// do something with the results / error
}];
i know its late but hope this helps!
[super viewDidLoad];
[self.searchDisplayController setDelegate:self];
[self.ibSearchBar setDelegate:self];
self.ibMapView.delegate=self;
// Zoom the map to current location.
[self.ibMapView setShowsUserLocation:YES];
[self.ibMapView setUserInteractionEnabled:YES];
[self.ibMapView setUserTrackingMode:MKUserTrackingModeFollow];
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
[locationManager startUpdatingLocation];
[self.ibMapView setRegion:MKCoordinateRegionMake(locationManager.location.coordinate, MKCoordinateSpanMake(0.2, 0.2))];
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.region = self.ibMapView.region;
request.naturalLanguageQuery = #"restaurant";
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error){
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
results = response;
if (response.mapItems.count == 0)
NSLog(#"No Matches");
else
for (MKMapItem *item in response.mapItems)
{
NSLog(#"name = %#", item.name);
NSLog(#"Phone = %#", item.phoneNumber);
[_matchingItems addObject:item];
MKPointAnnotation *annotation =
[[MKPointAnnotation alloc]init];
annotation.coordinate = item.placemark.coordinate;
annotation.title = item.name;
[self.ibMapView addAnnotation:annotation];
}
}];
}
Make the following steps to display nearest places.
Using google API find the Nearest Places Google Places API
The google API provide LAt and Long and address Informations.
Then Store the LAt and Long Values to Array then USing this lat and long values you can display Annotations in Apple map (iOS 6+) and Google Map (iOS 5).

how to check if Mapkit is available or not?

I am building an application that is using Mapkit. I know that this is only available in IOS6.
So I should check if this is available or not. I am using the following code.
if(NSClassFromString(#"MKMapKit")) {
// MKMapKit is available in this OS
CLLocationCoordinate2D coords =
CLLocationCoordinate2DMake(51.097185,5.621653);
NSDictionary *address = #{
(NSString *)kABPersonAddressStreetKey: #"Weg naar oqdffds 59",
(NSString *)kABPersonAddressCityKey: #"Msfsf",
(NSString *)kABPersonAddressStateKey: #"Limbusqfqsdf",
(NSString *)kABPersonAddressZIPKey: #"3670",
(NSString *)kABPersonAddressCountryCodeKey: #"BE",
(NSString *)kABPersonPhoneMainLabel:#"04741234567"
};
MKPlacemark *place = [[MKPlacemark alloc]
initWithCoordinate:coords addressDictionary:address];
MKMapItem *mapItem = [[MKMapItem alloc]initWithPlacemark:place];
mapItem.phoneNumber = #"0141343252";
//current location
MKMapItem *mapItem2 = [MKMapItem mapItemForCurrentLocation];
NSArray *mapItems = #[mapItem, mapItem2];
NSDictionary *options = #{
MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsMapTypeKey:
[NSNumber numberWithInteger:MKMapTypeStandard],
MKLaunchOptionsShowsTrafficKey:#YES
};
[MKMapItem openMapsWithItems:mapItems launchOptions:options];
}else {
NSLog(#"tot hier");
// MKMapKit is not available in this OS
locationController = [[MyCLController alloc] init];
locationController.delegate = self;
[locationController.locationManager startUpdatingLocation];
}
But for some reason or another it always use the google method.
Can anybody help!
As already mentioned, MapKit has been available well before iOS 6.
What you want to check for is MKMapItem (not "MKMapKit").
However, as the documentation for MKMapItem explains (with a code example):
To determine whether a class is available at runtime in a given iOS
release, you typically check whether that class is nil. Unfortunately,
this test is not cleanly accurate for MKMapItem. Although this class
was publicly available starting with iOS 6.0, it was in development
prior to that. Although the class exists in earlier releases, you
should not attempt to use it in those releases.
To determine at runtime whether you can use map items in your
application, test whether the class and the
openMapsWithItems:launchOptions: class method exist. That method was
not added to the class until iOS 6.0. The code might look like the
following:
Class itemClass = [MKMapItem class];
if (itemClass && [itemClass
respondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
// Use class
}
So this check:
if(NSClassFromString(#"MKMapKit")) {
should be:
Class itemClass = [MKMapItem class];
if (itemClass && [itemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
or:
Class itemClass = NSClassFromString(#"MKMapItem");
if (itemClass && [itemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
MkMapKit is available in ios 4.3, too, probably in 3.x, too!
What is new, is (like in all Releases), some new methods of MkMapKit:
You should better check for that specific method you need
(geocoding ?=
Look into the headers of MkMapKit you are importing (if i remeber correctly: MkMapKit.h), there are Macros defining the availability
of a specifc method, depending on the ios version.

Apple Map : get direction

How can I use Apple map for getting direction between two places?
I can provide the latitude and longitude of that two places?
Is it possible to show the direction in my app itself?
or Should I need to show the direction in the in built Map app of apple's iPhone?
You can send user to navigation app in iOS6 or google maps prior to iOS6.
Here's a sample code:
Class itemClass = [MKMapItem class];
if (itemClass && [itemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
// iOS 6 MKMapItem available
MKPlacemark* place = [[MKPlacemark alloc] initWithCoordinate:_targetLocation addressDictionary:nil];
MKMapItem* destination = [[MKMapItem alloc] initWithPlacemark:place];
destination.name = #"Name Here!";
NSArray* items = [[NSArray alloc] initWithObjects: destination, nil];
NSDictionary* options = [[NSDictionary alloc] initWithObjectsAndKeys:
MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsDirectionsModeKey, nil];
[MKMapItem openMapsWithItems:items launchOptions:options];
} else {
// Pre-iOS 6
CLLocationCoordinate2D coords = _lastLocation.coordinate;
NSString *stringURL = [NSString stringWithFormat:#"http://maps.google.com/maps?saddr=%g,%g&daddr=%g,%g", coords.latitude, coords.longitude, _targetLocation.latitude, _targetLocation.longitude];
NSURL *url = [NSURL URLWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
}
Here is the working code for showing directions on Apple map. It'll work for current place to your destination place and you just need to pass lat & long of destination place.
double destinationLatitude, destinationLongitude;
destinationLatitude=// Latitude of destination place.
destinationLongitude=// Longitude of destination place.
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)])
{
// Create an MKMapItem to pass to the Maps app
CLLocationCoordinate2D coordinate =
CLLocationCoordinate2DMake(destinationLatitude,destinationLongitude);
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate
addressDictionary:nil];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:#"Name/text on destination annotation pin"];
// Set the directions mode to "Driving"
// Can use MKLaunchOptionsDirectionsModeDriving instead
NSDictionary *launchOptions = #{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving};
// Get the "Current User Location" MKMapItem
MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];
// Pass the current location and destination map items to the Maps app
// Set the direction mode in the launchOptions dictionary
[MKMapItem openMapsWithItems:#[currentLocationMapItem, mapItem]
launchOptions:launchOptions];

Forward Geocoding with CLGeocoder Issues

I'm having an issue using forward geocoding on iOS5 with the geocodeAddressString function.
I have a MKMapView open up as a modal view to display different locations with data grabbed from the internet. My issue is when I dismiss the modal view, and then open it up again. On second try, only about half of my annotations are actually placed on the map. On a third try, none show up.
I have a feeling my issue here has to do with memory management and the scope of the CLGeocoder, but I just can't figure it out.
I create all of my annotations in the ViewDidLoad function of the view controller containing the MapView. Here is the code I use to get the coordinates of the addresses:
int locationCount = 0;
for(NSDictionary *date in locations)
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:[NSString stringWithFormat:#"%#, %#", [date objectForKey:#"venue"], [date objectForKey:#"location"]] completionHandler:^(NSArray *placemarks, NSError *error)
{
// if we find the exact location (including the venue string), create an annotation for the map
if(placemarks && placemarks.count > 0)
{
CLPlacemark *topResult = [placemarks objectAtIndex:0];
TourAnnotation *placemarkAnnotation = [[TourAnnotation alloc] initWithLocation:topResult.location andDetails:date];
placemarkAnnotation.tag = locationCount;
[tourMap addAnnotation:placemarkAnnotation];
}
// if not place an annotation at the center of the city
else
{
[geocoder geocodeAddressString:[date objectForKey:#"location"] completionHandler:^(NSArray *placemarks, NSError *error)
{
if(placemarks && placemarks.count > 0)
{
CLPlacemark *topResult = [placemarks objectAtIndex:0];
TourAnnotation *placemarkAnnotation = [[TourAnnotation alloc] initWithLocation:topResult.location andDetails:date];
placemarkAnnotation.tag = locationCount;
[tourMap addAnnotation:placemarkAnnotation];
}
}];
}
}];
++locationCount;
}
Any suggestions would be appreciated.
If it's memory issues have you considered how the annotation are dequeued and reused, the map view has a delegate method to do such a thing.
This tutorial may be of some assistance.
Ray Wenderlich map tutorial

Xcode iOS 4.2.1 -> Give Map View the address to show the pin? [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Forward Geocode Example using CLGeocoder
I have a plist full of names and their adrresses. I want my iOS app to show on a map view a pin with the address of the person he has selected. Can I import the address to map view and get a pin? And how?? Thank you.
Use the CLGeocoder class to convert addresses into lat/long coordinates:
Forward Geocode Example using CLGeocoder
The more accurate address you have, the better the result should be so with exact addresses you should get very accurate points.
Another option is to use Google's geocoding web service, simply pass the address string to this function and you will get an CLLocationCoordinate2D which contains a latitude & longitude.
Right now it grabs the location at the 0th index, which is the closest matching result. Log out the result to see the JSON response from Google.
- (CLLocationCoordinate2D) geoCodeUsingAddress:(NSString *)address
{
NSString *esc_addr = [address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *req = [NSString stringWithFormat:#"http://maps.google.com/maps/api/geocode/json?sensor=true&address=%#", esc_addr];
CLLocationCoordinate2D center;
NSString *result = [NSString stringWithContentsOfURL:[NSURL URLWithString:req] encoding:NSUTF8StringEncoding error:NULL];
if (result)
{
//NSLog(#"LOC RESULT: %#", result);
NSError *e;
NSDictionary *resultDict = [NSJSONSerialization JSONObjectWithData: [result dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: &e];
NSArray *resultsArray = [resultDict objectForKey:#"results"];
if(resultsArray.count > 0)
{
resultDict = [[resultsArray objectAtIndex:0] objectForKey:#"geometry"];
resultDict = [resultDict objectForKey:#"location"];
center.latitude = [[resultDict objectForKey:#"lat"] floatValue];
center.longitude = [[resultDict objectForKey:#"lng"] floatValue];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Results Found" message:#"No locations were found using, please try again." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
}
//goes through each result
/*for(NSDictionary *dict in resultsArray)
{
resultDict = [dict objectForKey:#"geometry"];
resultDict = [resultDict objectForKey:#"location"];
}*/
}
return center;
}
This is whats known as Forward Geocoding, and there is no built in API to do this for you. You need to use an external service, which one you use really depends on your app.
I have used Google's service for this. http://code.google.com/apis/maps/documentation/geocoding/
It is a very simple API, but has restrictions based on your app's license. I know there are a couple other services for this, but I'll leave that as an exercise to you.