I have a number of annotations on my map, in addition to the users current location. This works fine, except the default color for the users current location is the same as all of the other annotations. I'd like to make the pin green for the users current location so that it's uniquely identifiable from the other pins. How do I do this?
Bellow is the method I've been using (I can't find a way to determine which annotation is the users current location):
- (MKAnnotationView *)mapView:(MKMapView *)mapViewLocal viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"Pin";
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (pinView == nil)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier] autorelease];
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
If you use standard MKUserLocation type for user location then you can check annotation's type if it is the same:
...
if ([annotation isKindOfClass:[MKUserLocation class]]){
// This is annotation for user location
}
Related
I'm implementing a custom pin for a map, the image is in te project's folder but didn't show.
Perhaps (and very likely) I'm doing something wrong.
The map displays and shows the pins (default red pins) but not the custom image nor the UIButtonTypeDetailDisclosure
This is the code I'm using:
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// in case it's the user location, we already have an annotation, so just return nil
if ([annotation isKindOfClass:[MKUserLocation class]])
{
return nil;
}
static NSString *TheAnnotationIdentifier = #"theAnnotationIdentifier";
MKAnnotationView *shoppeAnnotationView =
[self.mapView dequeueReusableAnnotationViewWithIdentifier:TheAnnotationIdentifier];
if (shoppeAnnotationView == nil)
{
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:TheAnnotationIdentifier];
annotationView.canShowCallout = YES;
annotationView.image = [UIImage imageNamed:#"pin.png"];
annotationView.rightCalloutAccessoryView = [ UIButton buttonWithType:UIButtonTypeDetailDisclosure ];
annotationView.opaque = NO;
return annotationView;
}
return nil;
}
Any hints?
Thank you!
I implemented MKMapViewDelegate method below and customized user location annotation was displayed. However, the annotation did not move when I walked around with the iPhone. When I removed this delegate method, default the blue dot user location annotation followed me.
Please tell me how to move customized user location annotation:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
}
else
{
pinView.annotation = annotation;
}
pinView.image = [UIImage imageNamed:#"star.png"];
return pinView;
}
I have created a MKAnnotationView and do add a UIButton on it. Now I would like that button to remove the pin it is in.
This is how I add the button:
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pinAnnotation = nil;
if(annotation != myMapView.userLocation)
{
NSString *defaultPinID = [[NSString alloc] initWithFormat:#"pin%d",pinCount];
pinAnnotation = (MKPinAnnotationView *)[myMapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinAnnotation == nil )
pinAnnotation = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinAnnotation.canShowCallout = YES;
//// ADDING MY BUTTON
UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinAnnotation.rightCalloutAccessoryView = deleteButton;
//// ADDING IT'S ACTION
[deleteButton addTarget:self action:#selector(deletePin) forControlEvents:UIControlEventTouchUpInside];
}
pinCount++;
return pinAnnotation;
}
As you can see there, I set the action to call this method:
-(void)deletePin
{
//What to put here...?
}
How can I make that action delete it's button's pin?
I figured maybe sending the id thru or something, but am not sure how.
With annotation callout accessory views, do not use your own target/action method.
Instead, use the map view's calloutAccessoryControlTapped delegate method which will make this job much easier.
Remove the addTarget line and your custom method. Then implement the delegate method instead:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
[mapView removeAnnotation:view.annotation];
}
Also, unrelated, but the way you are setting the re-use identifier is wrong and defeats re-usability by assigning a different id to every annotation. The following is recommended:
- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pinAnnotationView = nil;
if (annotation != myMapView.userLocation)
{
NSString *reuseId = #"StandardPin";
pinAnnotationView = (MKPinAnnotationView *)[myMapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if ( pinAnnotationView == nil )
{
pinAnnotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId] autorelease];
pinAnnotationView.canShowCallout = YES;
UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
pinAnnotationView.rightCalloutAccessoryView = deleteButton;
}
else
//update annotation property if view is being re-used...
pinAnnotationView.annotation = annotation;
}
return pinAnnotationView;
}
Get the sender in your callback
[deleteButton addTarget:self action:#selector(deletePin:) forControlEvents:UIControlEventTouchUpInside];
-(void)deletePin:(id)sender
{
//What to put here...?
}
Then get the MKAnnotation associated with the MKPinAnnotationView, remove it from the MKMapView's annotations and redraw ([mapView setNeedsDisplay])
Hello friends,
I want to develop a functionality MKMapView in iPhone and to show the custom pin in MKAnnotation so please could anyone provide me a link or any idea about this functionality.
Thanks in advance.
You would need to specify annotation image in the viewForAnnotation delegate method
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString * const kAnnotationId = #"VumeliveAnnotation";
MKPinAnnotationView *annotationView = nil;
if ([annotation isKindOfClass:[CustomAnnotation class]])
{
annotationView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:kAnnotationId];
if (annotationView == nil) {
annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:kAnnotationId] autorelease];
annotationView.canShowCallout = YES;
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
[annotationView setImage:[UIImage imageNamed:<your image name>]];
}
return annotationView;
}
My MKMapView shows my position at startup but then the image never 'follows' me. The location gets updated and the screen does follow me, but the original "User Location" image stays behind.
Here is some code snippets:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(!pinView)
{
MKPinAnnotationView *customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
if(annotation == mapView.userLocation) customPinView.image = [self rotate:[UIImage imageNamed:#"myCar.png"] orientation:UIImageOrientationUp];
else customPinView.image = [UIImage imageNamed:#"randomPin.png"];
customPinView.animatesDrop = NO;
customPinView.canShowCallout = YES;
return customPinView;
}
else
{
pinView.annotation = annotation;
}
return pinView;
}
-(void)locationUpdate:(CLLocation *)location
{
CLLocationCoordinate2D loc = [location coordinate];
if(isFollowing)
[myMapView setCenterCoordinate:loc];//Works
}
and in my viewDidLoad I do call: [myMapView setShowsUserLocation:YES]; which does work.
So basically somewhere I neglect updating my position or its most possibly where I draw the new image for my current position.
Can anyone possibly see what I am missing or doing wrong there for it to not follow my location updates?
Thanks.
It's not clear if this is the issue but the viewForAnnotation method doesn't look right.
The annotation image is only being set when an annotation view is created. If a view is re-used, the annotation property is updated but not the image. It's possible that the re-used view is for an annotation of a different type requiring a different image.
The method should look something like this:
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
static NSString* AnnotationIdentifier = #"Annotation";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView)
{
pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
}
else
{
pinView.annotation = annotation;
}
if (annotation == mapView.userLocation)
pinView.image = [self rotate:[UIImage imageNamed:#"myCar.png"] orientation:UIImageOrientationUp];
else
pinView.image = [UIImage imageNamed:#"randomPin.png"];
return pinView;
}