2

I´m declaring a button:

let button = UIButton(frame: CGRect(x: ?, y: ?, width: 50, height: 50))

But I´m note sure how to set x and y relative to the Safe Area so that it works good on both >= iOS 11 and <= iOS 10.

I tried to use self.view.safeAreaInsets but it returns 0.0 for some reason. Any ideas how to solve this?

user9400347
  • 43
  • 1
  • 3
  • First of all you should use autoloayout if possible. In which place are putting this code, maybe it's to early? try in other places like viewDidLayoutSubviews – mkowal87 Feb 23 '18 at 13:50
  • I´m setting the button in viewDidAppear – user9400347 Feb 23 '18 at 13:53
  • I wonder if - because you are *not* using auto layout - you'll run into issues with the answer supplied by @Adis. An example.... Let's say `viewDidAppear` executes in portrait. You'll get a "Y" value that takes into account the notch, but your "X" value won't. Now, rotate counter-clockwise, or move the notch to the left. I'm pretty sure your button will be obscured by the notch. It might be a good idea to test this out before coding more. –  Feb 23 '18 at 14:32
  • @dfd, my app is only Portrait, would it still be an issue? – user9400347 Feb 24 '18 at 14:16
  • Probably not, but keep in mind that "notch". Portrait only means it can be on the bottom too. –  Feb 24 '18 at 14:21

3 Answers3

3

For iOS 11:

self.view.safeAreaInsets will be zero if you call it on viewDidLoad, viewWillAppear, etc

It should have the value if you call it on viewDidLayoutSubviews, viewDidAppear

Max Cruz
  • 1,215
  • 13
  • 17
2

I have same question when make animations.

Finally solved question, idea:create a frame equal safeArea frame.

(Device Orientaion only Left and Right)

CGRect safeAreaFrame;

if (@available(iOS 11.0, *)) {
    UIEdgeInsets safeAreaInsets = self.view.safeAreaInsets;
    safeAreaFrame = CGRectMake(safeAreaInsets.left,
                               safeAreaInsets.top,
                               self.view.frame.size.width - safeAreaInsets.left - safeAreaInsets.right,
                               self.view.frame.size.height - safeAreaInsets.top - safeAreaInsets.bottom);
} else {

    safeAreaFrame = self.view.frame;
}

then you have safe area frame use, for example:

UIView *view = [[UIView alloc] initWithFrame:safeAreaFrame];
view.backgroundColor = UIColor.redColor;
[self.view addSubview:view];

Note: The safe area insets return (0, 0, 0, 0) in viewDidLoad, hence they are set later than viewDidLoad, put into viewSafeAreaInsetsDidChange or viewDidAppear. I hope this will help you.

liu jeff
  • 21
  • 4
1

This would be far easier if you used autolayout and constraints, but you can get the margins of the safe area this way:

if #available(iOS 11.0, *) {
    if let window = UIApplication.shared.keyWindow {
        let topMargin =  window.safeAreaInsets.top
        let leftMargin =  window.safeAreaInsets.left
    }
}
Adis
  • 4,512
  • 2
  • 33
  • 40