Snapkit: Document how to use Safe Area Layout Guide iOS 11

Created on 13 Sep 2017  Â·  16Comments  Â·  Source: SnapKit/SnapKit

New Issue Checklist

  • [x] I have looked at the Documentation
  • [x] I have read the F.A.Q.
  • [x] I have filled out this issue template.

Issue Info

Info | Value |
-------------------------|-------------------------------------|
Platform | e.g. ios
Platform Version | e.g. 11.0
SnapKit Version | e.g. 3.0.0
Integration Method | e.g. carthage/cocoapods/manually

Issue Description

iOS 11 introduced a new layout guide, Safe Area Layout Guide, which is meant to replace the top/bottom layout guides. This is required for the new iPhoneX

https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/

enhancement

Most helpful comment

This is possible already, though some documentation could be helpful. safeAreaLayoutGuide is a UILayoutGuide, which is already relatable in SnapKit via snp. Example:

let subview = UIView()
addSubview(subview)
subview.snp.makeConstraints { make in
  if #available(iOS 11, *) {
    make.top.equalTo(safeAreaLayoutGuide.snp.topMargin)
  } else {
    make.top.equalTo(self)
  }
}

All 16 comments

This is possible already, though some documentation could be helpful. safeAreaLayoutGuide is a UILayoutGuide, which is already relatable in SnapKit via snp. Example:

let subview = UIView()
addSubview(subview)
subview.snp.makeConstraints { make in
  if #available(iOS 11, *) {
    make.top.equalTo(safeAreaLayoutGuide.snp.topMargin)
  } else {
    make.top.equalTo(self)
  }
}

@sprint84 @marclove is right here, you can already do this out of the box, and I don't think there's really a better way to do this because the safe area layout guides are on a view controller rather than a view and we don't extend view controller APIs

This is now in the docs, but I'm going to leave this issue open for awhile because it will prevent a bajillion new ones as people start to support safe layout areas.

As of Xcode 9 GM, safeAreaLayoutGuide has been moved to UIView's property.

https://developer.apple.com/documentation/uikit/uiview

@phamquochoan it's still a UILayoutGuide and an already accessible property. I suppose it could make sense to do something like .snp.safeArea but it may be confusing of whether that is hitting the view controller or the view itself…

I just check the documentation of UIView and UIViewController, the safeAreaLayoutGuide is removed from UIViewController

UIViewController

var additionalSafeAreaInsets: UIEdgeInsets
Custom insets that you specify to modify the view controller's safe area.

UIView

var safeAreaInsets: UIEdgeInsets
The insets that you use to determine the safe area for this view.

var safeAreaLayoutGuide: UILayoutGuide
The layout guide representing the portion of your view that is unobscured by bars and other content.

So if you could make .snp.safeArea, it would be 💯

I've made an extension that you can use (XCode8/9 compatibility):

extension UIView {

    var safeArea: ConstraintBasicAttributesDSL {

        #if swift(>=3.2)
            if #available(iOS 11.0, *) {
                return self.safeAreaLayoutGuide.snp
            }
            return self.snp
        #else
            return self.snp
        #endif
    }
}

Usage example:

let subview = UIView()
addSubview(subview)
subview.snp.makeConstraints { make in
    make.top.equalTo(self.safeArea.top)
}

@nunojfg - Thank you! For others consuming, don't forget to import SnapKit so ConstraintBasicAttributesDSL is defined. Cheers.

Will this extension give 20 as margin in top for statusbar when running pre ios11 @nunojfg ? Doesn't seem like it. Anyone has a suggestion for how to do that?

@jalmaas haven't tried since the app I'm developing doesn't have StatusBar, however it should work since I'm using safeAreaLayoutGuide for iOS11+ and no safeAreaLayoutGuide for iOS10-.
If it doesn't work the other solution is to use the height value from UIApplication.shared.statusBarFrame.size.height

How can I create a ConstraintBasicAttributesDSL with the statusbarframeheight to return?

Something like this?

let subview = UIView()
addSubview(subview)
subview.snp.makeConstraints { make in
    make.top.equalTo(self.safeArea.top).offset(UIApplication.shared.statusBarFrame.size.height)
}

That would leave double statusbaroffset in ios 11? I was thinking more like this in the category (not working code):
extension UIView {

    var safeArea: ConstraintBasicAttributesDSL {

        #if swift(>=3.2)
            if #available(iOS 11.0, *) {
                return self.safeAreaLayoutGuide.snp
            }
            return LayoutGuide(createWithTopAnchor20).snp
        #else
            return LayoutGuide(createWithTopAnchor20).snp
        #endif
    }
}

Apple's recommendation for bottom-of-the-screen-full-width buttons is to add padding on sides (because it will be pushed up from the bottom by the safe area) -- but it isn't clear to me the preferred way to do that -- without using some kind of "is this iPhone X" conditional. Am I missing something?

make.leading.trailing.bottom.equalTo(self.additionalSafeAreaInsets.bottom)

iOS 11 & Onwards :

import SnapKit
extension UIView {
    var safeArea : ConstraintLayoutGuideDSL {
        return safeAreaLayoutGuide.snp
    }
}

How to use:

containerView.snp.makeConstraints { (make) in

      make.leading.trailing.equalToSuperview()
      make.bottom.equalTo(view.safeArea.bottom)

}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

cooler333 picture cooler333  Â·  5Comments

monowerker picture monowerker  Â·  11Comments

Shehryar picture Shehryar  Â·  7Comments

swiftli picture swiftli  Â·  9Comments

tcurdt picture tcurdt  Â·  16Comments