Safe area layout guides in xib files - iOS 10

2019-01-30 04:46发布

I started adapting my app for iPhone X and found an issue in Interface Builder. The safe area layout guides are supposed to be backwards compatible, according to official Apple videos. I found that it works just fine in storyboards.

But in my XIB files, the safe area layout guides are not respected in iOS 10.

They work fine for the new OS version, but the iOS 10 devices seem to simply assume the safe area distance as zero (ignoring the status bar size).

Am I missing any required configuration? Is it an Xcode bug, and if so, any known workarounds?

Here is a screenshot of the issue in a test project (left iOS 10, right iOS 11):

safe area alignment on top of the screen

9条回答
在下西门庆
2楼-- · 2019-01-30 05:31

I added a NSLayoutConstraint subclass to fix this problem (IBAdjustableConstraint), with a @IBInspectable variable, looks like this.

class IBAdjustableConstraint: NSLayoutConstraint {

    @IBInspectable var safeAreaAdjustedConstant: CGFloat = 0 {
        didSet {
            if OS.TenOrBelow {
                constant += safeAreaAdjustedConstantLegacy
            }
        }
    }
}

And OS.TenOrBelow

struct OS {
    static let TenOrBelow = UIDevice.current.systemVersion.compare("10.9", options: NSString.CompareOptions.numeric) == ComparisonResult.orderedAscending
}

Just set that as the subclass of your constraint in IB and you will be able to make < iOS11 specific changes. Hope this helps someone.

查看更多
Fickle 薄情
3楼-- · 2019-01-30 05:35

Currently, backward compatibility doesn't work well.

My solution is to create 2 constraints in interface builder and remove one depending on the ios version you are using:

  • for ios 11: view.top == safe area.top
  • for earlier versions: view.top == superview.top + 20

Add them both as outlets as myConstraintSAFEAREA and myConstraintSUPERVIEW respectively. Then:

override func viewDidLoad() {
    if #available(iOS 11.0, *) {
        view.removeConstraint(myConstraintSUPERVIEW)
    } else {
        view.removeConstraint(myConstraintSAFEAREA)
    }
}
查看更多
别忘想泡老子
4楼-- · 2019-01-30 05:35

For me, a simple fix for getting it to work on both versions was

    if #available(iOS 11, *) {}
    else {
        self.edgesForExtendedLayout = []
    }

From the documentation: "In iOS 10 and earlier, use this property to report which edges of your view controller extend underneath navigation bars or other system-provided views. ". So setting them to an empty array makes sure the view controller does not extend underneath nav bars.

Docu is available here

查看更多
登录 后发表回答