Custom image for annotation pin in mkmapview - objective-c

Custom annotation pin changes to default red pin at long tap.
- (MKAnnotationView *) mapView:(MKMapView *)mapingView viewForAnnotation:(id <MKAnnotation>) annotation {
MKPinAnnotationView *annView = nil;
if(annotation != mapingView.userLocation)
{
static NSString *defaultPinID = kDEFAULTPINID;
annView = (MKPinAnnotationView *)[mapingView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( annView == nil )
annView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] ;
annView.canShowCallout = YES;
annView.image = [UIImage imageNamed:#"icon.png"];//sets image for default pin
}
return annView;
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKPinAnnotationView *)view
{
if ([[view.annotation title] isEqualToString:#"AnnotationTitle"] ) {
view.image = [UIImage imageNamed:#"selected_IconImage.png"];
}
}
Just touching the annotation pin the selected image appears.
But on long tap on the pin custom image reverts to default red pin.
How to fix this issue?

Use an MKAnnotationView instead of an MKPinAnnotationView, I'm guessing the map view performs some sort of reset, which goes back to the default image (which is the pin image you see)

Related

How can I Drop and Drag a pin on a map in Objective-C

Hope someone can help, I'm trying to implement dropping one single Pin on a mapView. But I want the pin to be able to be dragged around and and dropped and for this annotation to be separate from the annotation for the user's location. Whilst the below code works, it creates duplicate pins for a user's touch and the pins can not be dragged around:
- (void)dropPinFromPress:(UIGestureRecognizer *)recognizer {
// Add Pin from User's Touch
if (recognizer.state != UIGestureRecognizerStateBegan) {
return;
}
// convert touched position to map coordinate
CGPoint userTouch = [recognizer locationInView:self.mapView];
CLLocationCoordinate2D mapPoint = [self.mapView convertPoint:userTouch toCoordinateFromView:self.mapView];
// Add Pin from user's touch
Annotation *pin = [[Annotation alloc]initWithLocation:mapPoint];
[self.mapView addAnnotation:pin];
}
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
MKAnnotationView *a = [ [ MKAnnotationView alloc ] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
// a.title = #"test";
if ( a == nil )
a = [ [ MKAnnotationView alloc ] initWithAnnotation:annotation reuseIdentifier: #"currentloc" ];
NSLog(#"%f",a.annotation.coordinate.latitude);
NSLog(#"%f",a.annotation.coordinate.longitude);
CLLocation* currentLocationMap = [[[CLLocation alloc] initWithLatitude:a.annotation.coordinate.latitude longitude:a.annotation.coordinate.longitude] autorelease];
[self coordinatesToDMS:currentLocationMap];
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:a reuseIdentifier:#"currentloc"];
if(a.annotation.coordinate.longitude == mapView.userLocation.coordinate.longitude || a.annotation.coordinate.latitude == mapView.userLocation.coordinate.latitude )
{
if ([annotation isKindOfClass:MKUserLocation.class])
{
//user location view is being requested,
//return nil so it uses the default which is a blue dot...
return nil;
}
//a.image = [UIImage imageNamed:#"userlocation.png"];
//a.pinColor=[UIColor redColor];
}
else
{
// annView.image =[UIImage imageNamed:#"map-pin.png"];
//PinFirst=FALSE;
//annView.pinColor = [UIColor redColor];
// annView.annotation=annotation;
}
annView.animatesDrop = YES;
annView.draggable = YES;
annView.canShowCallout = YES;
return annView;
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
NSLog(#"map Drag");
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
fromOldState:(MKAnnotationViewDragState)oldState;
{
NSLog(#"pin Drag");
if (newState == MKAnnotationViewDragStateEnding)
{
CLLocationCoordinate2D droppedAt = view.annotation.coordinate;
NSLog(#"Pin dropped at %f,%f", droppedAt.latitude, droppedAt.longitude);
CLLocation* draglocation = [[[CLLocation alloc] initWithLatitude:droppedAt.latitude longitude:droppedAt.longitude] autorelease];
}
}

MKAnnotation looses title and subtitle when given a custom icon

Ok so I am making an iOS application using the MapKit framework. I have got the functionality working but am now having trouble when changing the icon of the annotation. I can change the annotations icon but when I do so the annotation looses it's title and subtitle values (nothing pops up when tapped). I think maybe the issue is due to something like not giving the annotation an identifier when first made but I am not sure...
If anyone could let me know whats going on it would be greatly appreciated!
The code to add annotation is:
-(void)addAnnotationAtLattitude:(double)lattitude withLongitude:(double)longitude withTitle:(NSString *)title withSubtitle:(NSString *)subtitle{
//Handles the adding off the anotation
CLLocationCoordinate2D annotationCoord;
annotationCoord.latitude = lattitude;
annotationCoord.longitude = longitude;
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init];
annotationPoint.coordinate = annotationCoord;
annotationPoint.title = title;
annotationPoint.subtitle = subtitle;
[self.MessageMap addAnnotation:annotationPoint];
}
and the code to change the icon (via delegate method ) is:
-(MKAnnotationView *)mapView:(MKMapView *)_mapView viewForAnnotation:(id
<MKAnnotation>)annotation
{
static NSString *AnnotationViewID = #"annotationViewID";
MKAnnotationView *annotationView = (MKAnnotationView *)[_mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];
if (annotationView == nil)
{
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationViewID];
}
annotationView.image = [UIImage imageNamed:#"CustomMapAnnotationIcon"];//mycustom image
annotationView.annotation = annotation;
return annotationView;
}
Are annotationView.enabled and annotationView.canShowCallout set to YES?

calloutAccessoryControlTabbed delegate does not get called

It doesn't give me any errors or warnings as well. I don't know what other relevant info or details I can provide. Please tell me if it's not enough.
_mapView.delegate is set to self
Method in which the calloutAccessoryControl is set:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
NSLog(#"Enter viewForAnnotation delegate");
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MapViewAnnotation class]]) {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else {
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
UIImageView *callOutButtonImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrow.png"]];
annotationView.rightCalloutAccessoryView = callOutButtonImage;
annotationView.image=[UIImage imageNamed:#"green-node.png"];
return annotationView;
}
return nil;
}
calloutAccessoryControlTabbed:
-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{
NSLog(#"Control Tabbed!");
_scrollView.hidden = false;
}
The following is from the mapView:annotationView:calloutAccessoryControlTapped: discussion in the MKMapViewDelegate protocol reference document:
Accessory views contain custom content and are positioned on either side of the annotation title text. If a view you specify is a descendant of the UIControl class, the map view calls this method as a convenience whenever the user taps your view. You can use this method to respond to taps and perform any actions associated with that control. For example, if your control displayed additional information about the annotation, you could use this method to present a modal panel with that information.
I can see that you've added a UIImage to your annotation view's right callout accessory view. A UIImage object does not inherit from UIControl. A UIButton object would work.

iOS 5 custom annotation not showing its title

I wrote this code to create a custom annotation image
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
static NSString *google = #"googlePin";
if ([annotation isKindOfClass:[myClass class]])
{
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:google];
if (!annotationView)
{
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:google];
annotationView.image = [UIImage imageNamed:#"pin.png"];
}
return annotationView;
}
return nil;
}
The image is appearing on the map; however when I click on it nothing happen, no title nor subtitle.
Do you guys have any idea?
When you override viewForAnnotation, you have to set canShowCallout to YES (the default on a new view you alloc/init is NO).
If you don't override that delegate method, the map view creates a default red pin with canShowCallout already set to YES.
However, even with canShowCallout set to YES, the callout will still not appear if the annotation's title is nil or blank (empty string).
(But again, if the title is not nil and not blank, the callout won't show unless canShowCallout is YES.)
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:google];
if (!annotationView)
{
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:google];
annotationView.image = [UIImage imageNamed:#"pin.png"];
annotationView.canShowCallout = YES; // <-- add this
}
else
{
// unrelated but should handle view re-use...
annotationView.annotation = annotation;
}
return annotationView;

Showing the Pin Information by Default

I am working with MKPinAnnotationView annotations pins over a MKMapView. Into the view that I am developing, there is a map centered on a pin. When I call the view the pin drops down and if I make a click over it, it shows the annotation information (canShowCallout = YES). How I can get this callout just when I open the view? Without making a click over the annotation pin.
Thanks for reading.
Edited:
I am using this code.
- (void)viewDidLoad {
[super viewDidLoad];
AddressAnnotation *annotation = [[[AddressAnnotation alloc] initWithCoordinate:self.currentAnnotationCoordinate] autorelease];
[self.mapView addAnnotation:annotation];
[self zoomCoordinate:self.currentAnnotationCoordinate];
}
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>)annotation {
// If it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
else { // Handles the other annotations.
// Try to dequeue an existing pin view first.
static NSString *AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if (!pinView) {
// If an existing pin view was not available, creates one.
MKPinAnnotationView *customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
customPinView.animatesDrop = YES;
customPinView.canShowCallout = YES;
// Adds a detail disclosure button.
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
customPinView.rightCalloutAccessoryView = rightButton;
return customPinView;
} else
pinView.annotation = annotation;
}
return nil;
}
- (void)mapViewDidFinishLoadingMap:(MKMapView *)theMapView {
AddressAnnotation *annotation = [[[AddressAnnotation alloc] initWithCoordinate:self.currentAnnotationCoordinate] autorelease];
for (id<MKAnnotation> currentAnnotation in mapView.annotations) {
if ([currentAnnotation isEqual:annotation]) {
[mapView selectAnnotation:currentAnnotation animated:FALSE];
}
}
}
Edited:
Calling didAddAnnotationViews: instead of mapViewDidFinishLoadingMap: (as aBitObvious has commented), it works fine.
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
id<MKAnnotation> myAnnotation = [self.mapView.annotations objectAtIndex:0];
[self.mapView selectAnnotation:myAnnotation animated:YES];
}
Possible duplicate: How to trigger MKAnnotationView's callout view without touching the pin?
You want to call [mapView selectAnnotation:].