How to specify offset from safe area in iOS below 11?
The versions of iOS before iOS 11 do not have safe area insets. These started with the introduction of iPhone X (shipped with iOS 11).
There is no need to compensate for these insets on older versions of iOS.
This is what your code should look like for backwards compatibility
var frame: CGRect
if #available(iOS 11.0, *) {
frame = CGRect(x:0,
y: self.view.safeAreaInsets.top + 16,
width: 100,
height: 50)
} else {
frame = CGRect(x:0,
y: topLayoutGuide.length + 16,
width: 100,
height: 50)
}
let customView = CustomView(frame: frame)
self.view.addSubview(customView)
Note:
If you are using the Safe Area Layout Guides for iOS 11, there are the topLayoutGuide
and bottomLayoutGuide
properties on UIViewController available for iOS 7 - 10.
How to specify offset from safe area in iOS below 11?
The versions of iOS before iOS 11 do not have safe area insets. These started with the introduction of iPhone X (shipped with iOS 11).
There is no need to compensate for these insets on older versions of iOS.
This is what your code should look like for backwards compatibility
var frame: CGRect
if #available(iOS 11.0, *) {
frame = CGRect(x:0,
y: self.view.safeAreaInsets.top + 16,
width: 100,
height: 50)
} else {
frame = CGRect(x:0,
y: topLayoutGuide.length + 16,
width: 100,
height: 50)
}
let customView = CustomView(frame: frame)
self.view.addSubview(customView)
Note:
If you are using the Safe Area Layout Guides for iOS 11, there are the topLayoutGuide
and bottomLayoutGuide
properties on UIViewController available for iOS 7 - 10.
Safe area layout guides in xib files - iOS 10
There are some issues with safe area layout and backwards compatibility. See my comment over here.
You might be able to work around the issues with additional constraints like a 1000 priority >= 20.0 to superview.top and a 750 priority == safearea.top. If you always show a status bar, that should fix things.
A better approach may be to have separate storyboards/xibs for pre-iOS 11 and iOS-11 and up, especially if you run into more issues than this. The reason that's preferable is because pre-iOS 11 you should layout constraints to the top/bottom layout guides, but for iOS 11 you should lay them out to safe areas. Layout guides are gone. Laying out to layout guides for pre-iOS 11 is stylistically better than just offsetting by a min of 20 pixels, even though the results will be the same IFF you always show a status bar.
If you take this approach, you'll need to set each file to the correct deployment target that it will be used on (iOS 11, or something earlier) so that Xcode doesn't give you warnings and allows you to use layout guides or safe areas, depending. In your code, check for iOS 11 at runtime and then load the appropriate storyboard/xibs.
The downside of this approach is maintenance, (you'll have two sets of your view controllers to maintain and keep in sync), but once your app only supports iOS 11+ or Apple fixes the backward compatibility layout guide constraint generation, you can get rid of the pre-iOS 11 versions.
By the way, how are you displaying the controller that you're seeing this with? Is it just the root view controller or did you present it, or..? The issue I noticed has to do with pushing view controllers, so you may be hitting a different case.
Swift Safe Area Layout not activating properly
Check my code solution. I added your function to the button when it is tapped and it now presents the GettingStartedController()
:
private let previousButton : UIButton = {
let button = UIButton(type: .system)
button.setTitle("Prev", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(switchVC), for: .touchUpInside)
return button
}()
fileprivate func setupBottomControls() {
view.addSubview(previousButton)
previousButton.backgroundColor = .red
view.addSubview(previousButton)
NSLayoutConstraint.activate([
previousButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
previousButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
previousButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
previousButton.heightAnchor.constraint(equalToConstant: 50)
])
}
@objc func switchVC(){
//enter GettingStarted controller
let controller = GettingStartedController()
present(UINavigationController(rootViewController: controller), animated: true,completion: nil) //used when no animation is present
}
Related Topics
Alert View Is Showing White Rectangle in iOS7
Ios:Retrieve Rectangle Shaped Image from the Background Image
Wrap Items in a Horizontal Uistackview on Multiple Lines
Swift - Error 'Expected ',' Separator' and 'Expected Expression in List of Expressions'
Correct Way to Setting a Tag to All Cells in Tableview
How to Check Version of a Cocoapods Framework
Xcode 5.1: Libcordova.A Architecture Problems
Convert Coordinates to City Name
How to Use the Uisearchbar and Uisearchdisplaycontroller
@Published Property Wrapper Not Working on Subclass of Observableobject
Nsinternalinconsistencyexception, Reason: Could Not Load Nib in Bundle
How to Convert an Uiimage to Grayscale in Swift Using Cifilter
iOS - Swift - Function That Returns Asynchronously Retrieved Value
Tableview Cell How Do We Resize Cell in Swift Along with Image and Label
Xcode 10, Command Codesign Failed with a Nonzero Exit Code
Keeping the Contentoffset in a Uicollectionview While Rotating Interface Orientation