Compass placing or position in a map view post iOS6 Compass placing or position in a map view post iOS6 ios ios

Compass placing or position in a map view post iOS6


My tests have shown, that the MKMapView somehow knows in what context it is displayed. If you use a regular UINavigationController you'll get the compass positioned below the navigation bar even when it is translucent.

There is a new UIViewController property in iOS 7 that defines the beginning of the actual content on the Y axis. It is called topLayoutGuide.

Sadly you cannot really influence the value that Apple uses to calculate this property in different contents. It also depends on the visibility of the status bar.

BUT: To solve this problem, I created a simple custom object that I return in my custom view controller:

@interface MiFixedLayoutGuide : NSObject <UILayoutSupport>@property (nonatomic) CGFloat pbLength;- (id)initWithLength:(CGFloat)length;@end@implementation MiFixedLayoutGuide- (id)initWithLength:(CGFloat)length {    self = [super init];    if (self) {        _pbLength = length;    }    return self;}- (CGFloat)length {    return _pbLength;}@end

Then I overrode the following two methods in my UIViewController subclass:

- (id<UILayoutSupport>)topLayoutGuide {    return [[MiFixedLayoutGuide alloc]initWithLength:44];}- (id<UILayoutSupport>)bottomLayoutGuide {    return [[MiFixedLayoutGuide alloc]initWithLength:44];}

This insets the layout guides by 44 points. And the MKMapView will use these values to position the compass at the top, and the "Legal" label at the bottom.

One thing that you now have to pay attention to is, that you cannot use the layout guides anymore within the auto layout visual format language.


With iOS 8 you can simple do:

[someMapView setLayoutMargins:UIEdgeInsetsMake(20, 0, 20, 0)];


Swift:

mapView.layoutMargins = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0)

Where instead of 20 you could calculate your UI elements height to have a more dynamic solution adjusting to each device or element.