MkMapView : Get lattitude and longitude when user moves the map - objective-c

i'am new to iphone MapView,when user moves the Map i need to get latitude and longitude of the visible region in iphone

You can get the coordinates of the point at the center of the map with the properties of the MKMapView :
centerCoordinate.latitude and centerCoordinate.longitude.
For example :
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(
map.centerCoordinate.latitude, map.centerCoordinate.longitude);
That's theses latitude and longitude you mean by "i need latitude and longitude when user moves map" ?
Hope this helps…

Use the .region property of your MKMapView.
MKMapView *myMapView = [[MKMapView alloc] initWithFrame:...];
MKCoordinateRegion region = myMapView.region;
// Center of the screen as lat/long
// region.center.latitude
// region.center.longitude
// width and height of viewing area as lat/long
// region.span.latitudeDelta
// region.span.longitudeDelta
Max

Add this in your Appdelegate.h
CLLocationManager *locationManager;
and then add these lines in your Appdelegate.m (didFinishLaunchingWithOptions)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startMonitoringSignificantLocationChanges];
[locationManager startUpdatingLocation];
this will call a method when you move with device,
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *currentLocation = [locations lastObject];
NSString *latitude = [NSString stringWithFormat:#"%g", currentLocation.coordinate.latitude];
NSString *longitude = [NSString stringWithFormat:#"%g", currentLocation.coordinate.longitude];
NSMutableArray *temp = [[NSMutableArray alloc] initWithCapacity:0];
[temp addObject:latitude];
[temp addObject:longitude];
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
[def setObject:temp forKey:#"CLocation"];
[temp release];
}
Use from this.

Related

Append Google Maps URL with Current Location

I am trying to compose an email with a Google Maps link using Core Location and MessageUI. Presently my code produces this string: https://maps.google.com?saddr=Current+Location&daddr=0.000000,0.000000.
I would like to append the device's longitude and latitude with the URL.
Here is my implementation:
#import "ViewController.h"
#interface ViewController () <CLLocationManagerDelegate>
#end
#implementation ViewController{
NSString *currentLongitude;
NSString *currentLatitude;
NSString *googleMapsURL;
CLLocationManager *locationManager_;
}
- (void)viewDidLoad {
[super viewDidLoad];
locationManager_ = [[CLLocationManager alloc] init];
locationManager_.delegate = self;
locationManager_.distanceFilter = kCLDistanceFilterNone;
locationManager_.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager_ requestAlwaysAuthorization];
[locationManager_ startUpdatingLocation];
}
- (IBAction)composeMailButton:(id)sender {
NSString *bodyHeader = #"Here are you directions:";
NSString *mailBody = [NSString stringWithFormat:#"%#\n%#", bodyHeader, googleMapsURL];
MFMailComposeViewController *emailComposer = [[MFMailComposeViewController alloc] init];
[emailComposer setSubject:#"Google Maps Directions"];
[emailComposer setMessageBody:mailBody isHTML:NO];
[emailComposer setToRecipients:#[#"castro.michael87#gmail.com"]];
[emailComposer setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentViewController:emailComposer animated:YES completion:nil];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *newLocation = [locations lastObject];
NSString *googleMapsURL = [[NSString alloc] initWithFormat:#"https://maps.google.com?saddr=Current+Location&daddr=%1.6f,%1.6f",newLocation.coordinate.latitude, newLocation.coordinate.longitude];
}
I am guessing that I have not correctly implemented the locationManager. Any input is very much appreciated!
First, you need to make use that you added the NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription in your info.plist file.
Second, your viewController need to implement the <CLLocationManagerDelegate>
#interface ViewController ()<CLLocationManagerDelegate>
Third, setup your locationManager in your viewDidLoad method.
locationManager_ = [[CLLocationManager alloc] init];
locationManager_.delegate = self;
locationManager_.distanceFilter = kCLDistanceFilterNone;
locationManager_.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager_ requestAlwaysAuthorization];
[locationManager_ startUpdatingLocation];
Fourth, implement the -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations method:
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *newLocation = [locations lastObject];
NSString *googleMapsURL = [[NSString alloc] initWithFormat:#"https://maps.google.com?saddr=Current+Location&daddr=%1.6f,%1.6f",newLocation.coordinate.latitude, newLocation.coordinate.longitude];
NSLog(#"%#", googleMapsURL);
}
Finally, if you test in simulator, you need to simulate a location:
Code Snippet: https://gist.github.com/ziyang0621/b1be760596da54873f81

Current Location returning 0

My Xcode app that I am developing needs to get the latitude and longitude of the users iOS device. Although currently all I get is 0 for both values. It does not ask for permission to have the location, and I am on a real device not a simulator.
NSLocationAlwaysUsageDescription is in my info.plist
I have also imported CoreLocation and in my .h file
#interface LocationViewController : UIViewController <CLLocationManagerDelegate>
in my .m file
#interface LocationViewController () <CLLocationManagerDelegate>
Here is my code:
#implementation LocationViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self getCurrentLocation];
}
-(CLLocationCoordinate2D) getLocation{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
return coordinate;
}
- (void)getCurrentLocation{
CLLocationCoordinate2D coordinate = [self getLocation];
NSString *latitude = [NSString stringWithFormat:#"%f", coordinate.latitude];
NSString *longitude = [NSString stringWithFormat:#"%f", coordinate.longitude];
NSLog(#"Latitude = %#", latitude);
NSLog(#"Longitude = %#", longitude);
}
Refer this answer. Hope, this helps.
Make this changes :
-(CLLocationCoordinate2D) getLocation{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager requestWhenInUseAuthorization];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
return coordinate;
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
NSLog(#"Status : %d", status);
}
Goto Settings > Privacy > Location > Your App > Always
And see how 'Status' value gets changes.
Put below before startUpdatingLocation
#ifdef __IPHONE_8_0
if(IS_OS_8_OR_LATER) {
// Use one or the other, not both. Depending on what you put in info.plist
[self.locationManager requestWhenInUseAuthorization];
}
#endif
[self.locationManager startUpdatingLocation];
Also call [self getCurrentLocation]; in viewDidLoad & viewDidAppear both.
It will work.
Also make sure you have entry for requestWhenInUseAuthorization in info.plist file too.
check this for more info

Location is displayed once

I am just playing with CLLocation class. i successfully done the below code. When i press a button it displays the location in ALert msg. When i click the same button again the location is displayed wrongly. And also i have noted eveytime i have to go to Setting - Privacy -Location services to enable access always everytime. When ever the app shows the current location correctly the Location access in Setting of iPhone goes to Blank. again i have to set it to Always to run the app . I have not added anything in .plists. I have wrote just the below code. My problem is It is showing correct location only for the first time after setting location accress to Always
-(CLLocationCoordinate2D) getLocation{
CLLocationCoordinate2D coordinate;
if ([CLLocationManager locationServicesEnabled])
{
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager requestWhenInUseAuthorization];
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
coordinate = [location coordinate];
}
return coordinate;
}
- (void)startTimer {
// if ([Run isEqualToString:#"can"]) {
i++;
NSLog(#"the i value %d", i);
Run =#"cant";
CLLocationCoordinate2D coordinate = [self getLocation];
CLGeocoder *ceo = [[CLGeocoder alloc]init];
CLLocation *loc = [[CLLocation alloc]initWithLatitude:coordinate.latitude longitude:coordinate.longitude]; //insert your coordinates
[ceo reverseGeocodeLocation:loc
completionHandler:^(NSArray placemarks, NSError error)
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSDictionary *eventLocation = [NSDictionary dictionaryWithObjectsAndKeys:placemark.name,#"NAME",placemark.subLocality,#"SUBLOCALITY" ,placemark.postalCode,#"POSTALCODE" ,nil];
LocationDetails= [NSMutableDictionary dictionaryWithObjectsAndKeys:eventLocation,#"value", nil];
NSString *name=placemark.name;
NSString *subLocality=placemark.subLocality;
NSString *postalCode=placemark.postalCode;
NSMutableArray *listData;
if (!listData) listData = [[NSMutableArray alloc] init];
[listData addObject:LocationDetails];
NSLog(#"the Location details %#", listData);
NSString *location=[NSString stringWithFormat:#"You are now in %# inside the sublocality of %# and pin code is %#",name,subLocality,postalCode];
UIAlertView *Alert=[[UIAlertView alloc]initWithTitle:#"Location Update" message:location delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[Alert show];
}
];
// }
// contains the code you posted to start the timer
}
- (IBAction)getLocation:(id)sender {
[ self startTimer];
}
Instead of using your getLocation method, do all your CLLocationManager initializations when the class is initialized. In your #interface set a property to hold the user's current location:
#property (nonatomic, strong) CLLocation *currentLocation;
And implement the delegate method -locationManager:didUpdateLocations: like so:
- (void)locationManager:(CLLocationManager*)manager didUpdateLocations:(NSArray*)locations
{
// set the current location. The most recent location is always at the end of the
// if there are multiple locations
_currentLocation = locations[locations.count - 1];
}
Then, instead of CLLocationCoordinate2D coordinate = [self getLocation];, get the location with:
CLLocationCoordinate2D coordinate = _currentLocation.coordinate; // I think that's the right property.
Note: Make sure you class conforms to CLLocationManagerDelegate

how to detect click on annotation mapkit and run action

I create one app that have mapkit and I can to add specific annotations in my map and I want when to tap (click) on any annotation do one method or one action but I don't about it.
please guide me . I searching many time in google but don't give correct answer for my question.
this is my code :
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
locationManager = [[CLLocationManager alloc] init];
[self GetMyLocation];
mapView = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, 320, 500)];
mapView.mapType = MKMapTypeStandard;
mapView.zoomEnabled = YES;
mapView.scrollEnabled = YES;
mapView.showsUserLocation = YES;
[mapView.userLocation setTitle:#"I'm Here"];
[mapView.userLocation setSubtitle:#"Rahnova Corpration"];
[self.view addSubview:mapView];
[self addAnnonations];
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPressGesture:)];
[self.mapView addGestureRecognizer:longPressGesture];
}
- (void) addAnnonations{
NSArray *title = [[NSArray alloc]initWithObjects:#"Rome",#"Chelsea", nil];
NSArray *subtitle = [[NSArray alloc]initWithObjects:#"Red",#"Blue", nil];
NSArray *latitude = [[NSArray alloc]initWithObjects:#"35.738000",#"35.739901", nil];
NSArray *longitude = [[NSArray alloc]initWithObjects:#"51.310029",#"51.312018", nil];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
[dictionary setObject:title forKey:#"title"];
[dictionary setObject:subtitle forKey:#"subtitle"];
[dictionary setObject:latitude forKey:#"latitude"];
[dictionary setObject:longitude forKey:#"longitude"];
for (int i = 0; i <= 1; i++) {
NSString *Name = [[dictionary objectForKey:#"title"]objectAtIndex:i];
NSString *SubName = [[dictionary objectForKey:#"subtitle"]objectAtIndex:i];
double Lati = [[[dictionary objectForKey:#"latitude"]objectAtIndex:i] doubleValue];
double Long = [[[dictionary objectForKey:#"longitude"]objectAtIndex:i] doubleValue];
[self SetTitle:Name SetSubtitle:SubName SetLatitude:Lati SetLongitude:Long];
}
}
- (void) SetTitle:(NSString *)title SetSubtitle:(NSString *)subtitle SetLatitude:(double)latitude SetLongitude:(double)longitude{
//create coordinate for use annotation
CLLocationCoordinate2D annoLocation;
annoLocation.latitude = latitude;
annoLocation.longitude = longitude;
Annotation *myAnnonation = [[Annotation alloc]init];
myAnnonation.coordinate = annoLocation;
myAnnonation.title = title;
myAnnonation.subtitle = subtitle;
[self.mapView addAnnotation:myAnnonation];
}
- (void) centerLocation{
//create region
MKCoordinateRegion myRegion;
CLLocationCoordinate2D center;
center.latitude = latitudes;
center.longitude = longitudes;
//span
MKCoordinateSpan span;
span.latitudeDelta = THE_SPAN;
span.longitudeDelta = THE_SPAN;
myRegion.center = center;
myRegion.span = span;
[mapView setRegion:myRegion animated:YES];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
longitudes = currentLocation.coordinate.longitude;
latitudes = currentLocation.coordinate.latitude;
[self centerLocation];
}
}
#pragma mark - MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
dude try this :
Xcode 4 iPhone SDK Tutorial - How to add different actions to each annotation-pin HD
or this :
Detecting when MKAnnotation is selected in MKMapView

GMMGeoTileImageData error with MapKit

In my viewcontroller I use Maps and I load a list of pins.
When I move the map or zoom in or out it, my app crashes and displays this error:
[GMMGeoTileImageData isEqualToString:]: unrecognized selector sent to instance 0x862d3b0
This is my code of the view controller:
- (void)viewDidLoad
{
statoAnn = [[NSMutableString alloc] initWithFormat:#"false"];
//bottone annulla per tornare indietro
UIBarButtonItem *annullaButton = [[[UIBarButtonItem alloc] initWithTitle:#"Annulla" style:UIBarButtonItemStylePlain target:self action:#selector(backView)] autorelease];
self.navigationItem.leftBarButtonItem = annullaButton;
//inizializzo la mappa
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 416)];
mapView.delegate = self;
mapView.mapType = MKMapTypeStandard;
[self.view addSubview:mapView];
[self setGmaps:arrData];
[super viewDidLoad];
}
/** inizializzo l'annotation del poi mappa **/
- (void) setGmaps:(NSMutableArray*)inputData {
// setto la lat e lng
CLLocationDegrees latitude;
CLLocationDegrees longitude;
CLLocationCoordinate2D poiLocation;
arrAnn = [[NSMutableArray alloc] init];
for(int i=0; i<[inputData count]; i++) {
//ricavo la lat e lng del pin
latitude = [[[inputData objectAtIndex:i] objectForKey:#"latitude"] doubleValue];
longitude = [[[inputData objectAtIndex:i] objectForKey:#"longitude"] doubleValue];
// setto la location del poi
poiLocation.latitude = latitude;
poiLocation.longitude = longitude;
//[[[CLLocation alloc] initWithLatitude:latitude longitude:longitude] autorelease];
//setto il pin
Annotation *ann = [[Annotation alloc] initWithCoordinate:poiLocation];
ann.title = [[inputData objectAtIndex:i] objectForKey:#"label"];
[arrAnn addObject:ann];
[ann release];
}
if (nil != self.arrAnn) {
[self.mapView addAnnotations:arrAnn];
//self.ann = nil;
self.arrAnn = nil;
}
}
/** setto il pin nella mappa ***/
- (void)setCurrentLocation:(CLLocation *)location {
MKCoordinateRegion region = {{0.0f, 0.0f}, {0.0f, 0.0f}};
region.center = location.coordinate;
region.span.longitudeDelta = 0.1f;
region.span.latitudeDelta = 0.1f;
[self.mapView setRegion:region animated:YES];
[self.mapView regionThatFits:region];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapViewTemp viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *view = nil; // return nil for the current user location
view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"identifier"];
if (nil == view) {
view = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"identifier"] autorelease];
view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
[view setPinColor:MKPinAnnotationColorPurple];
[view setCanShowCallout:YES];
[view setAnimatesDrop:YES];
if (![statoAnn isEqualToString:#"true"]) {
CLLocation *location = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude
longitude:annotation.coordinate.longitude];
[self setCurrentLocation:location];
statoAnn = [NSMutableString stringWithFormat:#"true"];
}
return view;
}
In viewForAnnotation, this line:
statoAnn = [NSMutableString stringWithFormat:#"true"];
sets statoAnn to an autoreleased string.
When the method exits, release is called on statoAnn and it no longer owns the memory it was pointing to. When the method is called again when you zoom or move the map, the memory that statoAnn was pointing to is now used by something else (GMMGeoTileImageData in this case). That object is not an NSString and doesn't have an isEqualToString: method and you get the error you are seeing.
To fix this, set statoAnn so the value is retained like you are doing in viewDidLoad. For example, you could change it to:
statoAnn = [[NSMutableString alloc] initWithFormat:#"true"];
You could also declare statoAnn as a property (#property (nonatomic, copy) NSString *statoAnn) and just set it using self.statoAnn = #"true";. The property setter will do the retaining for you.
However, you don't need to use a string to hold a "true" and "false" value. It's much easier and efficient to use a plain BOOL and you won't have to worry about retain/release since it's a primitive type and not an object.
The other thing is that viewForAnnotation is not the right place to be setting the map view's region in the first place. You can do that in viewDidLoad after the annotations are added.
Another thing: At the top of viewForAnnotation, you have the comment "return nil for the current user location" but that code doesn't do that. It just initializes the view to nil. To actually do what the comment says, you need this:
MKPinAnnotationView *view = nil;
// return nil for the current user location...
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
Finally, if the dequeueReusableAnnotationViewWithIdentifier does return a view (if view != nil), you need to set view.annotation to the current annotation since the re-used view may have been for a different annotation.