here is the project of this problem in the google drive: https://drive.google.com/file/d/1Js0t-stoerWy8O8uIOJl_bDw-bnWAZPr/view?usp=sharing
I make a custom navigation bar (the red view in the picture below) using IBDesignable code below. I want, if the iPhone has top notch like iPhone X, iPhone XR, then the height of custom navigation bar is 88, otherwise the height is 64. I make an IBDesignable code so I can reuse this code
import UIKit
@IBDesignable
class CustomParentNavigationBarView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
self.setHeight()
}
override func layoutSubviews() {
super.layoutSubviews()
self.setHeight()
}
func setHeight() {
let deviceHasTopNotch = checkHasTopNotchOrNot()
layer.frame.size.height = deviceHasTopNotch ? 88 : 64
}
func checkHasTopNotchOrNot() -> Bool {
if #available(iOS 11.0, tvOS 11.0, *) {
// with notch: 44.0 on iPhone X, XS, XS Max, XR.
// without notch: 20.0 on iPhone 8 on iOS 12+.
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}
}
I assign this CustomParentNavigationBarView
to the red view
and then, I put a label. that should located exactly below the red view (custom navigation bar, that uses IBDesignable)
it looks great if I run the app in the iPhone doesn't have top notch like iPhone8
but, if I run the app in iPhone that has top notch like iPhone XR, the label now inside the red view, it seems still following the previous autolayout to the red view height that previously 64 (in storyboard I am using iPhone 8), so when the custom navigation bar update to 88 when it is running on iPhone XR, the label still follow the previous 64 height, then it will locate inside the red view
here is the autolayout of custom nav bar (red view)
and here is the autolayout of the label
how to solve this issue ?
The problem here is that you specify the frame height in setHeight(), but also specify the height with a layout constraint inside storyboard. One way to fix this is to specify an intrinsicContentSize for your view and not specify the height as a layout constraint in storyboard. (I.o.w. similar to the way you rely on the width of the label to be calculated for you)
@IBDesignable
class CustomParentNavigationBarView: UIView {
lazy var deviceHasTopNotch: Bool = {
if #available(iOS 11.0, tvOS 11.0, *) {
// with notch: 44.0 on iPhone X, XS, XS Max, XR.
// without notch: 20.0 on iPhone 8 on iOS 12+.
return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20
}
return false
}()
override var intrinsicContentSize: CGSize {
let height:CGFloat = deviceHasTopNotch ? 88 : 64
let width = super.intrinsicContentSize.width //Use whatever you prefer here. Ex.UIScreen.main.bounds.size.width
return CGSize(width: width, height: height)
}
}
In Storyboard
Remove your current height constraint for the custom view. Set the Intrinsic Size
property to Placeholder
.
Example of the layout constraints for the custom nav bar.
来源:https://stackoverflow.com/questions/52814651/why-the-autolayout-is-not-updated-if-i-use-ibdesignable-file-when-i-run-the-app