How do I detect a single tap on an instance of MKMapView
? Do I have to subclass MKMapView
and then override the touchesEnded
method?
Thanks,
-Chris
How do I detect a single tap on an instance of MKMapView
? Do I have to subclass MKMapView
and then override the touchesEnded
method?
Thanks,
-Chris
If you're just looking to get notified of tap gestures without affecting any of the other touch behavior of the map, you'll want to use a UITapGestureRecognizer
. It's super simple, just put in some code like this.
UITapGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(didTapMap:)];
[theMKMapView addGestureRecognizer:tapRec];
[tapRec release];
That will call the didTapMap
whenever theMKMapView
receives a tap gesture and all the pinching, and dragging gestures will still work as they did before.
Or depending on what you are trying to do, add an MKAnnotation
(push pin, with a callout), so you have something to tap on - and then your map delegate will receive an event eg.
mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
Hope this will help : How to intercept touches events on a MKMapView or UIWebView objects?
Working Perfectly on iOS 8
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:nil];
doubleTap.numberOfTapsRequired = 2;
doubleTap.numberOfTouchesRequired = 1;
[self.mapView addGestureRecognizer:doubleTap];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[singleTap requireGestureRecognizerToFail: doubleTap];
[self.mapView addGestureRecognizer:singleTap];
}
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
return;
//Do your work ...
}
You cant at this time intercept touches on a map view, you can try layering an opaque view on there and see if it picks up touches...
Just add some code snippet as illustration of @tt-kilew answer. In my case, I want to point the user to itself on the map but do not want to interrupt his drag touch.
@interface PrettyViewController () <MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (assign, nonatomic) BOOL userTouchTheMap;
@end
@implementation PrettyViewController
#pragma mark - UIResponder
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
self.userTouchTheMap = [[touches anyObject].view isEqual:self.mapView];
}
#pragma mark - MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
//We just positioning to user
if (!self.userTouchTheMap) {
CLLocationDistance radius = 5000;
[self.mapView setRegion:MKCoordinateRegionMakeWithDistance(userLocation.location.coordinate, 2*radius, 2*radius) animated:YES];
}
}
@end
Nothing I ever found worked, but I came up with this unperfect solution : In viewDidLoad
let singleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(onMapClicked))
singleTapRecognizer.delegate = self
mapView.addGestureRecognizer(singleTapRecognizer)
In delegate :
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return touch.view!.frame.equalTo(mapView.frame)
}
my 2 cents for swit 5.x:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let v = touch.view
let ssv = v?.superview?.superview
if ssv === self.mapView{
searchBar.resignFirstResponder()
}
}
}
it works. but honestly can break if apple changes layers of views. better a recognizer.