Disable compass on MKMapView

13,507

Solution 1

You can disable the compass easily on OSX 10.9 / iOS 9 and later with the showsCompass property.

Objective-C:

mapView.showsCompass = NO;

Swift:

mapView.showsCompass = false

Hiding the compass this way will not prevent a custom MKCompassButton from acting and appearing as normal.

On iOS 8 or earlier, your choices are:

  1. Suck it up and live with it.

  2. Use a hack, like:

  3. If you're not rotating the map programatically and it hasn't already been rotated, disable rotation entirely, using

     mapView.rotateEnabled = NO;
    

The compass only shows up when the map is rotated, so by doing this you ensure that the compass is never triggered.

It's not clear to me why Apple waited so long to allow hiding the compass on iOS, and none of the options above are ideal. Pick whichever you think is the least bad in your case.

Solution 2

I found a solution to your problem, using Mark Amery's idea about traversing the MKMapView instance subviews to find the compass, along with the use of gesture recognition to trigger the removal event.

To find the compass I printed out the description of the views and found that one of the views was an instance of MKCompassView, this was obviously the compass.

I have come up with the following code that should work for you. It checks for a rotation gesture, and then removes the view in method triggered by the gesture event.

I have tested this method and it works well for me:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIRotationGestureRecognizer *rotateGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotate:)];

    [self.mapView addGestureRecognizer:rotateGesture];
}

-(void)rotate:(UIRotationGestureRecognizer *)gesture
{
    if ([gesture state] == UIGestureRecognizerStateBegan || [gesture state] == UIGestureRecognizerStateChanged) {
        // Gets array of subviews from the map view (MKMapView)
        NSArray *mapSubViews = self.mapView.subviews;

        for (UIView *view in mapSubViews) {
            // Checks if the view is of class MKCompassView
            if ([view isKindOfClass:NSClassFromString(@"MKCompassView")]) {
                // Removes view from mapView
                [view removeFromSuperview];
            }
        }
    }
}

Solution 3

Create a wrapper UIView with the frame you want for your map and clipsToBounds set to YES (or equivalently, Clip Subviews set in Interface Builder). Then put your MKMapView inside that wrapper view, with the y co-ordinate of the map's frame set to, for example, -80, and the height of the map set such that its vertical center is aligned with its parent.

Then the compass will be displayed but you cannot see it, because it is above the top of its parent view - problem solved.

Solution 4

Here is solution for Swift 4:

mapView.compassView.isHidden = true
Share:
13,507

Related videos on Youtube

BlackM
Author by

BlackM

iOS, tvOS, SQL

Updated on September 15, 2022

Comments

  • BlackM
    BlackM over 1 year

    I am using a MapView in my app to show some annotations. In iOS 7 a compass appears randomly on the map. I can't reproduce the error because it appears randomly but I want to disable it. Any ideas how to disable it?

    Update: I found out is not appears randomly but on a specific gesture. When you use 2 fingers and slide one right and the other left.

    • Craig
      Craig over 10 years
      That gesture is also known as "rotate"
  • BlackM
    BlackM over 10 years
    No, I need to show the user location. What I don't need is the compass.
  • BlackM
    BlackM over 10 years
    I found out is not appears randomly but on a specific gesture. When you use 2 fingers and the one slide right and the other left.
  • Vladislav Mazur
    Vladislav Mazur over 10 years
    Well, now I understand what you want. The only way docs show to us to disable map's rotating using rotateEnabled. This will prevent rotate Gesture from being enabled.
  • Vladislav Mazur
    Vladislav Mazur over 10 years
    And if you need to rotate your map, you can add UIRotationGestureRecognizer to map's view add rotate it in way you want using [mapView setTransform:CGAffineTransformMakeRotation(rotation)]; and annotations too.
  • AlexWien
    AlexWien over 10 years
    @VladislavMazur What is so difficult to understand? He want to disable the compass when he wants, and keep the rotation feature.
  • Matt H.
    Matt H. about 10 years
    Would this count as "using a private API," and get flagged during Apple's scan of your binary?
  • Mark Amery
    Mark Amery almost 10 years
    Nice - I'm surprised it turns out that this hack is so simple to implement and understand. I don't have access to a Mac nowadays, so I'm not able to test this, but will take your word for it that it works. I've edited a link to your answer into mine.
  • Andrei Marincas
    Andrei Marincas almost 9 years
    The rotate gesture doesn't work for me, but I implemented - (void)viewDidLayoutSubviews method of my view controller and moved the code there, now it works.