iOS 5 custom annotation not showing its title - objective-c

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;

Related

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.

Custom image for annotation pin in mkmapview

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)

MKAnnotationView for userLocation pin iPhone

I have an application that uses MKMapView and at some point in the app I need to remove all the current pins in the map using
[mapView removeAnnotations:mapView.annotations]
And then I want to show again the current user location
mapView.showUserLocation = YES
But I can only make it reappear as a regular pin, because the userLocation view class its not public so I cant return views of that type. Here is my code
- (MKAnnotationView *)mapView:(MKMapView *)theMapView viewForAnnotation:(id<MKAnnotation>)annotation
MKPinAnnotationView* annView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:#"currentloc"];
if (!annView) {
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
annView.pinColor = MKPinAnnotationColorRed;
annView.animatesDrop=TRUE;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
if ([annotation isKindOfClass:[DraggableAnnotationAM class]] ) annView.draggable =YES;
return annView;
}
else {
if ([annotation isKindOfClass:[DraggableAnnotationAM class]] ) annView.draggable = YES;
annView.annotation = annotation;
return annView;
}
Also I have found through reflection that
MKUserLocationView
is the class that is used to display the current location, but because its not public its not safe to use and my app keeps crashing and Im sure theres a easier way.
Is it possible to do what I want, or should I just never remove the user location annotation of the mapView?
Thanks in advance
If you only want to show a blue dot for the user's location in stead of a regular pin, return nil in this mapView delegate function. Alternatively return your own MKAnnotationView (subclass) object:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil // or return a custom MKAnnotationView
} else { // etc.
Try doing it with an NSMutableArray. Hope this helps you solving your problem!
NSMutableArray *annotation = [[NSMutableArray alloc] init];
for (id <MKAnnotation> annot_ in [mapView annotations])
{
if ( [annot_ isKindOfClass:[MKUserLocation class]] ) {
}
else {
[annotation addObject:annot_];
}
}
[mapView removeAnnotations:annotation];
[annotation release];
annotation = nil;

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:].