Detect Tap on CalloutBubble in MKAnnotationView
Could you add a gesture recognizer when you're initializing the MKAnnotationView
?
Here's the code for inside dequeueReusableAnnotationViewWithIdentifier:
UITapGestureRecognizer *tapGesture =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(calloutTapped:)];
[theAnnotationView addGestureRecognizer:tapGesture];
[tapGesture release];
The method for the gesture recognizer:
-(void) calloutTapped:(id) sender {
// code to display whatever is required next.
// To get the annotation associated with the callout that caused this event:
// id<MKAnnotation> annotation = ((MKAnnotationView*)sender.view).annotation;
}
MKAnnotationView and tap detection
There might be a better and cleaner solution but one way to do the trick is exploiting hitTest:withEvent:
in the tap gesture recognized selector, e.g.
suppose you have added a tap gesture recognizer to your _mapView
- (void)tapped:(UITapGestureRecognizer *)g
{
CGPoint p = [g locationInView:_mapView];
UIView *v = [_mapView hitTest:p withEvent:nil];
if (v == subviewOfKindOfClass(_mapView, @"MKAnnotationContainerView"))
NSLog(@"tap on the map"); //put your action here
}
// depth-first search
UIView *subviewOfKindOfClass(UIView *view, NSString *className)
{
static UIView *resultView = nil;
if ([view isKindOfClass:NSClassFromString(className)])
return view;
for (UIView *subv in [view subviews]) {
if ((resultView = subviewOfKindOfClass(subv, className)) break;
}
return resultView;
}
It's probably doesn't cover all the edge cases but it seems to work pretty well for me.
UPDATE (iOS >= 6.0)
Finally, I found another kind of solution which has the drawback of being valid only for iOS >= 6.0: In fact, this solution exploits the new -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
added to the UIView
s in this way
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// overrides the default value (YES) to have gestureRecognizer ignore the view
return NO;
}
I.e., from the iOS 6 onward, it's sufficient to override that UIView
method in each view the gesture recognizer should ignore.
How to detect taps on MKMapView but ignore taps on MKAnnotationViews
Finally worked it out for myself. The trick was to use the UIGestureRecognizerDelegate
to intercept the tap and decide whether or not the UITapGestureRecognizer
should handle it.
The following delegate method code checks what has been tapped on, and ignores it if it's an MKPinAnnotationView
:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
{
if (touch.view.self?.isKind(of: MKPinAnnotationView.self) == true)
{
return false
}
return true
}
Tapping an MKAnnotation to select it is REALLY slow
Unfortunately, there's nothing you can do about this. It's for the exact same reason that tapping links in Mobile Safari is slow: the gesture recognizers have to jostle for a while to decide whether you might be scrolling (dragging) before they agree that you are tapping.
So, it has nothing to do with the animation. It's just the nature of gesture recognition in this situation.
Prevent touch events on MKMapView being detected when a MKAnnotation is tapped
I think you will find the following links very useful:
http://blog.asynchrony.com/2010/09/building-custom-map-annotation-callouts-part-2/
How do I make a MKAnnotationView touch sensitive?
The first link discusses (among other things) how to prevent the propagation of touches to the annotations so that they selectively respond, and the second one how to detect the touches.
Detecting the tap which changes the selected annotation or deselects it
There is a delegate method for this. Just make sure you set the delegate
property of the map view to the containing view controller.
optional func mapView(_ mapView: MKMapView, didDeselect view:
MKAnnotationView)
This link may help you: https://developer.apple.com/documentation/mapkit/mkmapviewdelegate
Detect on calloutAccessoryControlTapped only the tap on rightCalloutAccessoryView
To achieve it you would need to add target for the right accessory view. You can achieve it by setting button to rightCalloutAccessoryView as shown in the code snippet.
class MapViewController: UIViewController, MKMapViewDelegate {
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is Annotation {
let annotationView = AnnotationView(annotation: annotation, reuseIdentifier: "reuseIdentifier")
let rightButton = UIButton(type: .DetailDisclosure)
rightButton.addTarget(self, action: #selector(didClickDetailDisclosure(_:)), forControlEvents: .TouchUpInside)
annotationView.rightCalloutAccessoryView = rightButton
}
return nil
}
func didClickDetailDisclosure(button: UIButton) {
// TODO: Perform action when was clicked on right callout accessory view.
}
}
// Helper classes.
class Annotation: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
init(coordinate: CLLocationCoordinate2D, title: String, subtitle: String) {
self.coordinate = coordinate
self.title = title
self.subtitle = subtitle
}
}
class AnnotationView: MKAnnotationView {
}
Related Topics
iOS 11 - Unable to Change Navigation Bar Height
Grouping Coredata by Date() in Swiftui List as Sections
Rounding Uiimage and Adding a Border
How to Launch My Settings Bundle from My Application
How to Detect When User Used Password Autofill on a Uitextfield
Googleutilities/Appdelegateswizzler/Private/Gulapplication.H' File > Not Found
Download PDF and Save to the "Files" in Iphone, Not to the App Data, Swift
How to Switch to Speaker Output When Bluetooth Headsets Are Connected
Recording from Remoteio: Resulting .Caf Is Pitch Shifted Slower + Distorted
How to Take Uiimage of Avcapturevideopreviewlayer Instead of Avcapturephotooutput Capture
How to Change Text Font in Uipickerview in iOS 7
Swift Framework Does Not Include Symbols from Extensions to Generic Structs
Error Using Swift - Instance Member Cannot Be Used on Type 'Viewcontroller'
Getting System Uptime in iOS/Swift
Xcode /Podfile.Lock: No Such File
How We Can Set the Light Content Style of Status Bar in iOS 9 for Whole Application