Although the process for doing this is well documented, I am unable to solve this problem.
All I want to do is to take the coordinate at which I have just created an annotation and have the map zoom in and center on it. I followed this tutorial with some modifications:
http://maybelost.com/2011/01/a-basic-mapview-and-annotation-tutorial/
The MapViewAnnotation class consists of just a title and the coordinates.
_detailItem is simply an object that holds a name, latitude, and longitude as strings.
I have a basic map. I'm using a storyboard (so, ARC). I have coordinates. Here's my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
// Set some coordinates for our position
CLLocationCoordinate2D location;
double thisLat = [_detailItem.EventLat doubleValue];
double thisLong = [_detailItem.EventLong doubleValue];
location.latitude = (double)thisLat;
location.longitude = (double)thisLong;
// Add the annotation to our map view
MapViewAnnotation *newAnnotation = [[MapViewAnnotation alloc] initWithTitle:_detailItem.EventName andCoordinate:location];
[self.map addAnnotation:newAnnotation];
}
// When a map annotation point is added, zoom to it
- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
{
MKAnnotationView *annotationView = [views objectAtIndex:0];
id <MKAnnotation> mp = [annotationView annotation];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate], 1000, 1000);
[mv setRegion:region animated:YES];
[mv selectAnnotation:mp animated:YES];
}
Yeah. When I do this, the annotations shows up as expected, but the map doesn't center on it or zoom in. During debug, I found that didAddAnnotationViews isn't being called at all! Yet, I've clearly made an explicit call to addAnnotation.
Help?
didAddAnnotationViews isn't being called at all
In your viewDidLoad implementation, add this line:
self.map.delegate = self;
See if that changes things.
Related
Struggling bad here on something I am now exhausted with. There are two parts here:
1) I am trying to get a pin removed if the user searches the same coordinate that is already identified and pinned on ViewDidLoad. This part WORKS. The non operable part is #2.
2) When the user searches ANY OTHER location, I want a pin added, i.e. [self.mapView addAnnotation:addAnnotation]; My code is below.
- (IBAction) showAddress // THIS IS A BUTTON WHICH LOCATES COORDINATES
{
[addressField resignFirstResponder];
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.2;
span.longitudeDelta=0.2;
CLLocationCoordinate2D location = [self addressLocation];
region.span=span;
region.center=location;
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
if (location.longitude = (double) -73.2125)
{
addAnnotation = [[AddressAnnotation alloc]initWithCoordinate:location];
[self.mapView removeAnnotation:addAnnotation];
}
else
{
addAnnotation = [[AddressAnnotation alloc]initWithCoordinate:location];
[self.mapView addAnnotation:addAnnotation];
[addAnnotation release];
}
}
Any thoughts? Thanks guys!
This line:
if (location.longitude = (double) -73.2125)
does an assignment (=), not a comparison (==).
Since the assignment is always successful, it always goes to the removeAnnotation part.
However, I don't recommend comparing doubles (or any floating-point numbers) using ==.
I suggest checking instead if the two numbers are within some small distance of each other.
See this answer for an example.
I am working on MapView,on which I have two buttons.
1)centreButton:
this button drops the pin annotation at the centre of the current map.
when this button is pressed, I am storing the last annotation in a NSMutable array.
then remove the last annotation from mapview and drop one pin at the centre of map
Code I have done for this part is as follows:
function for dropping the pin
- (void)PinDropwithlatitude:(double)lat longitude:(double)longi droptitle:(NSString *)title
{
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = lat;
theCoordinate.longitude = longi;
MKCoordinateRegion region;
region.center.latitude = theCoordinate.latitude;
region.center.longitude = theCoordinate.longitude;
//Set Zoom level using Span
MKCoordinateSpan span;
span.latitudeDelta =0.005;
span.longitudeDelta =0.005;
region.span = span;
[MapView setRegion:region animated:YES];
SetLat =lat;
SetLong =longi;
DDAnnotation *annotation = [[[DDAnnotation alloc] initWithCoordinate:theCoordinate addressDictionary:nil] autorelease];
annotation.title = title;
annotation.subtitle = [NSString stringWithFormat:#"%f %f", annotation.coordinate.latitude, annotation.coordinate.longitude];
[MapView addAnnotation:annotation];
}
when I press centre button I am doing the following code and store last array in annotation.
-(IBAction)CenterPressed:(id)sender
{
//40.439631,-3.698273 -spain centre
[lastAnnotation addObjectsFromArray:MapView.annotations];
NSLog(#"last annotation array=%#",lastAnnotation);
for (id annotation in [MapView annotations])
{
if ([annotation isKindOfClass:[MKUserLocation class]])
{
continue;
}
[MapView removeAnnotation:annotation];
}
[self PinDropwithlatitude:SetLat longitude:SetLong
droptitle:NSLocalizedString(#"Title", nil)];
}
the log for the array is showing me the
last annotations you can see below::
last annotation array=(
"<+40.43963100,-3.69827300> +/- 0.00m",
"<+40.43923187,-3.68722200> +/- 0.00m",
"<+40.43792343,-3.67670774> +/- 0.00m",
"<+40.43772888,-3.66711617> +/- 0.00m"
)
2)UNDOButton: which removes the currently placed annotation and redrop the previous annotation, for that i have removed the annotaion from mapview, and redrop the annotation last annotation from array which i have maintained previously,using the code:
-(IBAction)undoPressed:(id)sender
{
if ([lastAnnotation count]>0)
{
int countAnn = [lastAnnotation count];
[MapView removeAnnotation:[lastAnnotation objectAtIndex:countAnn-1]];
//[MapView delete:[lastAnnotation objectAtIndex:countAnn-1]];
[lastAnnotation removeObjectAtIndex:countAnn-1];
double latitude = [[[lastAnnotation objectAtIndex:[lastAnnotation count]-1] annotation]coordinate].latitude;
double longitude = [[[lastAnnotation objectAtIndex:[lastAnnotation count]-1]annotation]coordinate].longitude;
NSLog(#"count = %d",[lastAnnotation count]);
[self PinDropwithlatitude:latitude longitude:longitude droptitle:NSLocalizedString(#"Title", nil)];
}
}
but when i press the undo button it crashes with the following error
-[DDAnnotation annotation]: unrecognized selector sent to instance 0x79b8f40
I don't get to know, where exactly the problem arises. can any one please help me to point out my mistake in the above code.
thanks
can you try
[lastAnnotation lastObject]
instead of
[[lastAnnotation objectAtIndex:[lastAnnotation count]-1]
like
[MapView removeAnnotation:[lastAnnotation lastObject]];
[lastAnnotation removeObject:[lastAnnotation lastObject]];
I have loaded the custom annotation image for user current location.I am updating the current user location after every 1 sec in background.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self performSelectorOnMainThread:#selector(tempupdate) withObject:nil waitUntilDone:NO];
[pool release];
-(void)tempupdate
{
NSLog(#"callToLocationManager");
mylocationManager = [[CLLocationManager alloc]init];
NSLog(#"locationManagerM = %#",mylocationManager);
mylocationManager.delegate = self;
mylocationManager.desiredAccuracy = kCLLocationAccuracyBest;
mylocationManager.distanceFilter = 500;
[mylocationManager startUpdatingLocation];
}
After updating the current latutude and longitude i am refreshing the map using following code
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.002;
span.longitudeDelta=0.002;
CLLocationCoordinate2D location;
location.latitude=[lat doubleValue];
location.longitude=[longt doubleValue];
region.span=span;
region.center=location;
addAnnotation=[[AddressAnnotation alloc]initWithCoordinate:location];
addAnnotation.mTitle=#"You are here";
[self.mapView removeAnnotations:self.mapView.annotations];
[self.mapView addAnnotation:addAnnotation];
[self.mapView setRegion:region animated:TRUE];
[self.mapView regionThatFits:region];
But every time custom annotation image blinks before adding to the map.How to avoid this flicker effect?
I haven't tested this yet, but based on a quick glance at your code, I would guess the issue lies in your removal of the annotation and then adding a new one.
Have you tried just editing the already attached annotation's properties?
NSArray* curAnnotations = [mapView annotations];
AddressAnnotation* aa = [curAnnotations lastObject]; // I am assuming you only have 1 annotation
aa.mTitle = #"You are here"; // or don't do this if it never changes
[aa setCoordinate:location];
Note: Apple Docs specifically call out the 'setCoordinate' method as something that should be used to support dragging or frequent updates.
you mustn't remove annotation from map. Instead change the annotation coordinate in the UIView beginAnimations-commitAnimations block;
It will look something like this:
[UIView beginAnimations:#"yourAnimationName" context:nil];
[UIView setAnimationDuration:1.0];
[yourAnnotation setCoordinate:yourNewCoordinate];
[UIView commitAnimations];
It will move smoothly the annotation.
BR,
Marcin Szulc
//SWIFT 3
UIView.beginAnimations("yourname", context: nil)
UIView.setAnimationDuration(1.0)
yourpin.coordinate = MKCoordinateForMapPoint(mycoordinate)
UIView.commitAnimations()
I am implementing a mapView whereby an annotation will be placed when the user search for an address. But somehow, the annotation sometime doesn't move and update to the new coordinate. It's only upon zooming the map, then will it update to the new location. The subtitle did get updated though.
- (void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar {
SVGeocoder *geocodeRequest = [[SVGeocoder alloc] initWithAddress:searchBar.text inRegion:#"sg"];
[geocodeRequest setDelegate:self];
[geocodeRequest startAsynchronous];
}
- (void)geocoder:(SVGeocoder *)geocoder didFindPlacemark:(SVPlacemark *)placemark {
if (annotation) {
[annotation moveAnnotation:placemark.coordinate];
annotation.subtitle = [NSString
stringWithFormat:#"%#", placemark.formattedAddress];
}
else {
annotation = [[MyAnnotation alloc]
initWithCoordinate:placemark.coordinate
title:#"Tap arrow to use address"
subtitle:[NSString
stringWithFormat:#"%#", placemark.formattedAddress]];
[mapView addAnnotation:annotation];
}
MKCoordinateSpan span;
span.latitudeDelta = .001;
span.longitudeDelta = .001;
MKCoordinateRegion region;
region.center = placemark.coordinate;
region.span = span;
[mapView setRegion:region animated:TRUE];
[searchBar resignFirstResponder];
}
I don't think MKMapView gets notified of changes to an annotation's location. The documentation of MKAnnotation's setCoordinate: says: "Annotations that support dragging should implement this method to update the position of the annotation." so it seems that's the only purpose of this method is for supporting dragging of pins.
Try removing the annotation from the map view before changing its coordinates and then add it back to the map view.
Nothing in your code (that you've shown) tells mapView that the annotation's location has changed. The annotation itself probably can't do it in -moveAnnotation because annotations generally don't know what map or maps they've been added to (nor should they).
The right way to move an annotation is to to remove it from the MKMapView that's using it, update its location, and then add it back to the map. You can't just change the annotation's location after it has been added to the map because the map may very well cache the location or sort the annotation according to its location, and there's no method in MKMapView to tell the map that the location has changed.
I'd change your conditional to something like this:
if (annotation == nil) {
annotation = [[MyAnnotation alloc] init];
annotation.title = #"Tap arrow to use address";
}
[mapView removeAnnotation:annotation];
[annotation moveAnnotation:placemark.coordinate];
annotation.subtitle = placemark.formattedAddress;
[mapView addAnnotation:annotation];
This assumes that it's safe to call -init in place of -initWithCoordinate:title:subtitle:; if not, you'll want to change that.
I am working on a simple GPS-like app. I created a custom object which extends MKAnnotation which also works fine. I can place it etc, but if I put this piece of code [mpm setCoordinate:loc]; in my code, the app opens and freezes while showing the basic gray-grid (not showing any downloaded map and non of my buttons work either then)
Here is my header:
#interface FirstViewController : UIViewController <MKMapViewDelegate>
{
IBOutlet MKMapView *mapView;
MyPlaceMark *mpm;
}
-(void)locationUpdate:(CLLocation *)location;
-(void)locationError:(NSError *)error;
#end
And here is the piece of code where I try to update things:
-(void)locationUpdate:(CLLocation *)location
{
CLLocationCoordinate2D loc = [location coordinate];
[mpm setCoordinate:loc]; // This line messes it up.
[mapView setCenterCoordinate:loc];
if([mapView showsUserLocation] == NO)
[mapView setShowsUserLocation:YES]; // This does not show my position either?
}
If I comment that line out, the app works fine. I need to update the annotation as it will be my marker for showing the users current location. PS: Without that line, it does center my view - so location is a valid/set variable.
My viewDidLoad looks like this:
- (void)viewDidLoad {
mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
//mapView.showsUserLocation = YES;
[mapView setShowsUserLocation:YES];
mapView.mapType = MKMapTypeStandard;
mapView.delegate = self;
CLLocationCoordinate2D location;
MKCoordinateRegion region;
location.latitude = -33.8;
location.longitude = 18.6;
MKCoordinateSpan span;
span.latitudeDelta = 0.01;
span.longitudeDelta = 0.01;
region.span = span;
region.center = location;
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
mpm = [[MyPlaceMark alloc] initWithCoordinate:location]; // Creating mpm
[mapView addAnnotation:mpm]; // Adding mpm
[self.view addSubview:mapView];
[super viewDidLoad];
}
Should I re-add mpm after I changed it's location? Or would it just jump to its new location on the map?
So to recap the question: How can I update the custom MKAnnotation's location on my mapview?
Thank you for your time!
EDIT: I think the main reason for the crash is the fact that I do not create a setCoordinate method/function in my custom MKAnnotation. How would I override that but keep it same as original?
The error in log-console:
2011-06-09 14:42:40.377 AeroNav[3706:707] -[MyPlaceMark setCoordinate:]: unrecognized selector sent to instance 0x19e0e0
2011-06-09 14:42:40.493 AeroNav[3706:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyPlaceMark setCoordinate:]: unrecognized selector sent to instance 0x19e0e0'
...
terminate called after throwing an instance of 'NSException'
[mapView setShowsUserLocation:YES] doesn't update the region that the map shows. You will have to implement the delegate methods didUpdateUserLocation: and call the setRegion:animated: there to move the region to user's location. Until this is called for the first time, the userLocation property of MKMapView is not set.
As for the MKAnnotation thing, MKAnnotation is a protocol. It doesn't have a default implementation. You will have to provide for all the methods and properties that you've agreed to conform to. So declare a property pretty similar to the one in the MKAnnotation protocol.