首页 > 解决方案 > 如果我在运行应用程序时使用 IBDesignable 文件,为什么自动布局没有更新?

问题描述

这是谷歌驱动器中这个问题的项目:https ://drive.google.com/file/d/1Js0t-stoerWy8O8uIOJl_bDw-bnWAZPr/view?usp=sharing

我使用下面的 IBDesignable 代码制作了一个自定义导航栏(下图中的红色视图)。我想,如果 iPhone 有 iPhone X、iPhone XR 这样的顶级设备,那么自定义导航栏的高度为 88,否则高度为 64。我制作了一个 IBDesignable 代码,以便我可以重用此代码

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
    }

}

我将其分配CustomParentNavigationBarView给红色视图

在此处输入图像描述

然后,我贴了一个标签。应该正好位于红色视图下方(自定义导航栏,使用 IBDesignable)

如果我在 iPhone 上运行该应用程序看起来很棒没有像 iPhone8 那样一流 在此处输入图像描述

但是,如果我在 iPhone 中运行像 iPhone XR 这样一流的应用程序,标签现在在红色视图中,它似乎仍然遵循之前的自动布局到之前 64 的红色视图高度(在情节提要中我使用的是 iPhone 8),所以当自定义导航栏在 iPhone XR 上运行时更新到 88 时,标签仍然沿用之前的 64 高度,然后它会定位在红色视图内

在此处输入图像描述

这是自定义导航栏的自动布局(红色视图)

在此处输入图像描述

这是标签的自动布局

在此处输入图像描述

如何解决这个问题?

标签: iosswiftautolayoutibdesignable

解决方案


这里的问题是您在 setHeight() 中指定了框架高度,但也在情节提要内使用布局约束指定了高度。解决此问题的一种方法是为您的视图指定一个 intrinsicContentSize ,而不是将高度指定为情节提要中的布局约束。(类似于您依赖标签宽度为您计算的方式)

@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)
    }
}

在故事板中

删除自定义视图的当前高度约束。将 Intrinsic Size属性设置为Placeholder

自定义导航栏的布局约束示例。

在此处输入图像描述


推荐阅读