eloquentcoder

random brain dumps

Conditional Top Space to Container Constraint

16 January 2015

I don’t open Interface Builder very often. I haven’t opened it for so long, that I’ve missed all the stuff with constraints and autolayouts that were introduced in iOS6. That’s the price I’ve paid for doing UI programmatically only.

Few days ago I decided to stop being so ignorant to Interface Builder and I created a new view in XCode 6 with a UIImageView at the top which included a top space to container constraint (vertical space).

Nothing special. Then I presented that view by pushing it into an instance of UINavigationController.

Oops.

Top space to container doesn’t take into account a navigation bar, if one exists. Apparently there’s no way to set it up in Interface Builder which is odd, as it seems to be a common case. But it occured that doing it programmatically ain’t that hard because you can reference layout constraints as any other outlet from your interface:

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *lcTopVerticalSpace;

From this point it’s very easy to set up an appropriate condition in a view’s viewDidLoad method:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    if (self.navigationController) {
        CGFloat navigationBarHeight = 
            self.navigationController.navigationBar.frame.size.height;
        
        self.lcTopVerticalSpace.constant += navigationBarHeight;
    }
}

Done.

Update 24 Januray 2015

Although the trick I showed is valid and it has it’s usages, I’ve just stumbled upon something that was introduced in iOS 7 and clearly solves my problem. Starting with iOS 7 content of any view starts where a status bar begins - at the very top. Hence content of any view that’s displayed within UINavigationController is hidden by a status and navigation bars. To overcome this default behaviour simply set edgesForExtendedLayout property to an appropriate value. In my case it was:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
 
    self.edgesForExtendedLayout = UIRectEdgeNone;    
}

rafek

comments powered by Disqus