bllubbor bllubbor - 4 months ago 34
Objective-C Question

MKMapView hide navigationBar on tap like in photo app without losing functionality of MKMapView

I would like to hide and show the navigation bar on tap like the one in the photos app
BUT without losing the functionality of the MKMapView. the user should still be able to double tap for zoom, pinch and zoom and be able to select annotations.

I tried it with:

UITapGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(hideBar:)];
[self.myMKMapView addGestureRecognizer:tapRec];
[tapRec release];

But then the user can't select annotations anymore!And it also hides on double taps.

Any ideas ?


I know, it's almost exactly one year too late, but I hope somebody can make a use of it. Here's how I did it, based on @Cocoanetics's answer:

BOOL                mapReceivedDoubleTap;


UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapMap:)];
[tapGestureRecognizer setDelegate:self];
[_mapView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];


// ignore annotations
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    return (![[touch view] isKindOfClass:[MKAnnotationView class]]);

// take care of double taps for zoom
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer  shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

    if([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        UITapGestureRecognizer *tr = (UITapGestureRecognizer *)otherGestureRecognizer;
        if(tr.numberOfTapsRequired == 2)
            mapReceivedDoubleTap = YES;

    return NO;

- (void)didTapMap:(UITapGestureRecognizer *)tapGestureRecognizer {

    mapReceivedDoubleTap = NO;

    // hide/show on delay
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, .2f * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES];


import MapKit

class MapViewController: UIViewController, UIGestureRecognizerDelegate {

    @IBOutlet weak var myMapView: MKMapView!

    var mapReceivedDoubleTap = false

    override func viewDidLoad() {

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MapViewController.didTapMap(_:)))            
        tapGestureRecognizer.delegate = self            

    // ignore annotations
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        return !touch.isKindOfClass(MKAnnotationView)

    // take care of double taps for zoom
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer,
                           shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        if otherGestureRecognizer.isKindOfClass(UITapGestureRecognizer) {
            let tr = otherGestureRecognizer as! UITapGestureRecognizer
            if tr.numberOfTapsRequired == 2 {
                mapReceivedDoubleTap = true

        return false

    func didTapMap(gestureRecognizer: UIGestureRecognizer) {

        mapReceivedDoubleTap = false

        // hide/show on delay
        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.2 * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue(), {
            if !self.mapReceivedDoubleTap {
                self.navigationController?.setNavigationBarHidden(!(self.navigationController?.navigationBarHidden)!, animated: true)