1

This is driving me bonkers!

So, I have custom pins which you can drag around a map which works fine. Because I want them to animate like a standard apple pin (animatesDrop), I use the following event to follow whats going on.

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState

When a user has finished dragging a pin, I need to display a callout saying save/cancel. I fire off the following method, the MKPinAnnotationView (was a UIView) appears but the buttons don't work.

  • I have tried doing it all in code, did not work.
  • I have tried trapping the touch event on the view, did not work.
  • I have made sure the view is retained (selectedPin)
  • I have tried added the view to the superview (saw on a post)
  • I have made sure userInteractionEnabled was on
  • I made the view a controller, I am pretty sure that did not work either

I have had lots of sugar :(

- (void)createYuhuCalloutWithAnnotationView:(MKAnnotationView *)view
{
    MapAnnotation *mapAnnotation = (MapAnnotation *)view.annotation;
    MapYuhuCallout *calloutView = (MapYuhuCallout *)[[[NSBundle mainBundle] loadNibNamed:@"MapYuhuCallout" owner:self options:nil] objectAtIndex:0];

    CGRect calloutViewFrame = calloutView.frame;
    calloutViewFrame.origin = CGPointMake(-calloutViewFrame.size.width/2 + 10, -calloutViewFrame.size.height);
    calloutView.frame = calloutViewFrame;

    [calloutView.saveButton addTarget:self
                           action:@selector(saveYuhuChanges)
                 forControlEvents:UIControlEventTouchUpInside];

    [calloutView.cancelButton addTarget:self
                               action:@selector(cancelYuhuChanges)
                     forControlEvents:UIControlEventTouchUpInside];

    calloutView.leftCalloutAccessoryView = calloutView.saveButton;
    calloutView.rightCalloutAccessoryView = calloutView.cancelButton;

    calloutView.userInteractionEnabled = YES;
    view.userInteractionEnabled = YES;
    [view addSubview:calloutView];

    mapAnnotation.yuhuCalloutView = calloutView;

    self.currentCalloutView = calloutView;
    self.selectedPin = mapAnnotation;
}

UPDATE

I believe I know why this is working but I am not sure how to fix it. I am adding a UIView to a AnnotationView (PIN). The UIView Is a lot bigger than the pin so its frame is bigger. Only the part of the UIView that crosses over the pin is clickable. I expected ClipToBounds to hide the UIView.

So, it seems I need to add a UIView to the actual Map so thats it is clickable or make the AnnotationView (PIN) frame a lot bigger which would cause other issues.

Burf2000
  • 5,001
  • 14
  • 58
  • 117
  • [MKAnnotationView](https://developer.apple.com/library/ios/documentation/MapKit/Reference/MKAnnotationView_Class/Reference/Reference.html) is a abstract class your custom class is inheriting, have you overriding leftCalloutAccessoryView method and used it to return a view? – Shams Ahmed Apr 09 '14 at 11:30
  • Do you have an example mate? I did not think I needed to override anything on the class – Burf2000 Apr 09 '14 at 12:02
  • Sorry not atm, Can you describe what you mean by button doesn't work? do you mean addTarget doesnt fire? or button doesn't show? – Shams Ahmed Apr 09 '14 at 12:33
  • addTarget does not fire, not touch detection is detected, is it because its added as a subview to the pin and not to the map? – Burf2000 Apr 09 '14 at 12:38

2 Answers2

3

I have a long explanation on custom callout view here https://stackoverflow.com/a/19404994/1226370. In your case best practice would be to add view as subview of your calloutView, and calloutView itself make invisible.

All details about touch handling are described in linked answer.

Hope it will be useful!

Community
  • 1
  • 1
haawa
  • 3,078
  • 1
  • 26
  • 35
  • I had a look through and thought this would fix it but sadly it does not, thanks for the help though. I think my buttons are outside the annotations view and so not recieving touches – Burf2000 Apr 09 '14 at 12:53
  • Even if your buttons are inside of annotation view bound they will still ignore any touch input, because mapView handle touches differently (searching for closest pin to touch location), and due to that none of touch events will be sent to annotation subviews. You need to subclass MKAnnotationView and implement onHit methods anyway, even if your problem in something else, you will still have this problem. – haawa Apr 09 '14 at 13:03
  • I think your right actually, I think the view is being added to the pins view which is far to small, so any part of the view that overlaps the pin is clickable but anything outside of the frame wont – Burf2000 Apr 09 '14 at 13:06
  • It feels like I need to add it to the map – Burf2000 Apr 09 '14 at 13:06
1

Add the following Delegate method which gets called when any UIControl receives a event:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
        NSLog(@"tap event");
    }

If a view is a descendant of the UIControl, 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.

Shams Ahmed
  • 4,498
  • 4
  • 21
  • 27