Assuming you are running on a iPhone then this is expected behaviour and can be changed by overriding the following:
override var prefersStatusBarHidden: Bool {
return false
}
From the description of that UIViewController method:
By default, this method returns false with one exception. For apps
linked against iOS 8 or later, this method returns true if the view
controller is in a vertically compact environment.
If you override that then you will get a status bar in landscape orientation and the safe area guide will adapt accordingly.
EDIT
So a slight misunderstanding with the original requirement. It's not to show the status bar but to have a gap like if there had been a status bar.
This will need to be done manually as you can't setup constraints that only apply in certain orientations/size class manually.
This is a basic UIViewController that will do what you are looking for:
class ViewController: UIViewController {
var testView: UIView!
var landscapeConstraint: NSLayoutConstraint!
var portraitConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.testView = UIView()
self.testView.backgroundColor = .green
self.view.addSubview(self.testView)
self.testView.translatesAutoresizingMaskIntoConstraints = false
let guide = view.safeAreaLayoutGuide
self.testView.leftAnchor.constraint(equalTo: guide.leftAnchor, constant: 0).isActive = true
self.testView.rightAnchor.constraint(equalTo: guide.rightAnchor, constant: 0).isActive = true
self.testView.bottomAnchor.constraint(equalTo: guide.bottomAnchor, constant: 0).isActive = true
self.portraitConstraint = self.testView.topAnchor.constraint(equalTo: guide.topAnchor, constant: 0)
self.landscapeConstraint = self.testView.topAnchor.constraint(equalTo: guide.topAnchor, constant: 20) // Hardcoded the size but this can be anything you want.
switch self.traitCollection.verticalSizeClass {
case .compact:
self.landscapeConstraint.isActive = true
case.regular:
self.portraitConstraint.isActive = true
default: // This shouldn't happen but let's assume regular (i.e. portrait)
self.portraitConstraint.isActive = true
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
super.willTransition(to: newCollection, with: coordinator)
switch newCollection.verticalSizeClass {
case .compact:
self.portraitConstraint.isActive = false
self.landscapeConstraint.isActive = true
case.regular:
self.landscapeConstraint.isActive = false
self.portraitConstraint.isActive = true
default: // This shouldn't happen but let's assume regular (i.e. portrait)
self.landscapeConstraint.isActive = false
self.portraitConstraint.isActive = true
}
}
}
Basically you set up the fixed constraints, i.e. left, right and bottom, and then setup constraints for portrait and landscape (regular and compact vertical size class) which are both disabled by default.
Then you decide which one to activate based on the current orientation/size class.
Then you override the:
willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
method and swap active state of the two constraints based on the new orientation/size class.
One thing to note is to always deactivate constraints first and then activate ones to avoid anything complaining about constraints that can't be satisfied.