Smooth Movement of annotation image on Mapview - iphone

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()

Related

Centering MKMapView on an annotation

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.

mapView "addAnnotation:addAnnotation" NOT dropping pin as desired with IF/ELSE statements

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.

Crashed while removing the pin from mapview

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]];

How to have multiple annotations on a mapview based on an array

The below code is what I have used so far, and it loops through every object in the array correctly, but when I try to make them all display on one map it only adds the last obeject in the array to the map, not all 20 or so I want to display.
self.clientTable = [ClientDatabase database].clientTable;
ClientTable *info = nil;
[_nameLabel setText:info.name];
[_stateLabel setText:info.state];
//change the string to doubles for the map GPS co-ordinates
double latDouble = [info.latMap doubleValue];
double longDouble = [info.longMap doubleValue];
NSLog(#"%d",[self.clientTable count]);
int countArray = [self.clientTable count];
for (int i=0;i<countArray;i++) {
info = [self.clientTable objectAtIndex:i];
info.uniqueId=i;
NSLog(#" i = %d ; id = %d %#",i, info.uniqueId, info.name);
//set up the map
[super viewDidLoad];
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
MKCoordinateRegion region = {{0.0,0.0},{0.0,0.0}};
region.center.latitude = latDouble;
region.center.longitude = longDouble;
region.span.longitudeDelta =0.02; //degrees of acuracy, most precise best for this time
region.span.latitudeDelta =0.02; //degrees of accuracy
[mapView setRegion:region animated:YES];
// set up the annotation point
AllMap *annotationPoint = [[AllMap alloc] init];
annotationPoint.title = info.name;
annotationPoint.subtitle = info.state;
annotationPoint.coordinate = region.center;
[mapView addAnnotation:annotationPoint];
annotationPoint.isAccessibilityElement=YES;
//show annotation by default
[mapView selectAnnotation:annotationPoint animated:YES];
[mapView setDelegate:self];
}
Sorry if the code is rubbishy, i'm new to iPhone programming.
Thanks in advance :D
It looks like you're calling [super viewDidLoad] inside your for loop, which is probably resetting the mapView's annotations array. This method should only be called once, so if you move it before the for statement you may get better results.
why are you setting up the map inside of the loop where you are creating the annotations?
here is an old blog posting, but it covers the basics and should get you back on track

Why didn't my map annotation move?

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.