iOS 6, Auto Layout and MKMapView

I’m currently in the throws of updating an app for iOS 7. As part of the update, I’m throwing out all the XIBs and buying fully into using auto layout programatically.

I’ve been concentrating on getting it all to work on iOS 7 and only started at looking at how it looks on iOS 6 this week. Straight away I hit an issue

Auto Layout still required after executing -layoutSubviews. MKMapView's implementation of -layoutSubviews needs to call super.

The solution turns out to fairly straight forward. You don’t seem to be able to directly apply constraints between a MKMapView and another subview under iOS 6. Instead, you place your map into a container view and set the autoresizingMask to flexible width and height. You can then apply any constraints needed to the container view.

The code below simply creates a MKMapView which takes up the whole screen. From there, you could add buttons to the container view that are constrained to float 30 points from the bottom (which is what I needed to do).

self.mapContainerView = [[UIView alloc] initWithFrame:CGRectZero];
self.mapContainerView.translatesAutoresizingMaskIntoConstraints = NO;

self.mapView = [[MKMapView alloc] initWithFrame:self.mapContainerView.frame];
self.mapView.showsUserLocation = YES;
self.mapView.delegate = self;
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.mapContainerView addSubview:self.mapView];

[self.view addSubview:self.mapContainerView];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_mapContainerView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_mapContainerView)]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_mapContainerView]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_mapContainerView)]];

As an aside: Reveal has been invaluable in debugging my auto layout issues.

4 thoughts on “iOS 6, Auto Layout and MKMapView”

  1. Using the code posted raises the following error…

    2014-01-16 19:08:22.755 MappaMundiWithAutolayout[886:60b] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Unable to parse constraint format:
    Unable to interpret ‘|’ character, because the related view doesn’t have a superview
    |[_mapContainerView]|
    ^’

    I found the mapContainerView wasn’t added to the view, so I made that modification and tweaked the constraintsWithVisualFormat slightly.

    – (void)viewDidLoad
    {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.mapContainerView = [[UIView alloc] initWithFrame:CGRectZero];
    self.mapContainerView.translatesAutoresizingMaskIntoConstraints = NO;

    self.mapView = [[MKMapView alloc] initWithFrame:self.mapContainerView.frame];
    self.mapView.showsUserLocation = YES;
    self.mapView.delegate = self;
    self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.mapContainerView addSubview:self.mapView];
    [self.view addSubview:self.mapContainerView];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@”H:|[mapContainerView]|” options:0 metrics:nil views:@{@”mapContainerView”:self.mapContainerView}]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@”V:|[mapContainerView]|” options:0 metrics:nil views:@{@”mapContainerView”:self.mapContainerView}]];
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>