ios - 从 Xib 加载的 UIView 不能正确应用 AutoLayout

标签 ios autolayout storyboard xib ios-autolayout

我正在尝试将我的 View Controller 内容分解为从 xib 加载的更小的单个 View block 。我这样做是通过将占位符 UIView 对象放入我的 Storyboard View Controller 中,并使用它们添加我在 xib 文件中作为 subview 布置的实际 UIView 子类在构建时。

这个过程非常简单,是 discussed before .

但是,问题在于 xib 文件中定义的 AutoLayout 约束在我添加 View 时不起作用。

为了说明这个问题,我创建了一个示例项目:ViewController 有一个类型为 CustomColorViewcolorView( 的子类>UIView) 将添加到普通 UIView 占位符。 CustomColorView 类有一个 coloredView 的属性,它应该填充整个空间(由 xib 文件中每一边的 AutoLayout 约束定义)。

ViewController

enter image description here

NibLoadable 协议(protocol):

public protocol NibLoadable {
    static var nibName: String { get }
}

public extension NibLoadable where Self: UIView {

    public static var nibName: String {
        return String(describing: Self.self)
    }

    public static var nib: UINib {
        let bundle = Bundle(for: Self.self)
        return UINib(nibName: Self.nibName, bundle: bundle)
    }

    func setupFromNib() {
        guard let loadedView = Self.nib.instantiate(withOwner: self, options: nil).first as? UIView else { fatalError("Error loading \(self) from nib") }
        loadedView.frame = bounds

        addSubview(loadedView)
        loadedView.translatesAutoresizingMaskIntoConstraints = false
        loadedView.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
        loadedView.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        loadedView.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
        loadedView.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
    }
}

当我将自定义 View 添加到普通 UIView 时,我会假设它应用了 nib 文件中所有已定义的约束,但事实并非如此。两个 View 的 print 结果应该相同,但它们不同(coloredView 仍然具有来自 xib 文件的大小)。

有什么可能出错的想法吗?感谢您的帮助!

整个项目都在 GitHub 上:XibAutoLayoutExample

最佳答案

您的 View 高度正确,请添加 layer.borderColorlayer.borderWidth 并检查

func setup() {
    print("CustomColorView bounds: \(bounds)")
    print("coloredView subview bounds: \(coloredView.bounds)")
    self.coloredView.layer.borderColor = UIColor.red.cgColor
    self.coloredView.layer.borderWidth = 1
}

此外,如果您在 viewDidAppear 中调用 setup() 将显示正确的值,这是因为 viewDidAppearviewDidLayoutSubviews< 之后执行 因此,当您的 viewController 正确结束其布局时,您的日志会显示正确的值

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    colorView.setup()
}

日志

CustomColorView bounds: (0.0, 0.0, 320.0, 227.0)
coloredView subview bounds: (0.0, 0.0, 320.0, 227.0)

关于ios - 从 Xib 加载的 UIView 不能正确应用 AutoLayout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48822981/

相关文章:

ios - UIActivityIndi​​catorView 不以屏幕为中心,特别是当 UITableView 是 Root View 时

ios - [UIBarItem setTitle :]: unrecognized selector sent to instance

ios - 默认系统项目的自定义背景

ios - 如何在 swift 中的标签中嵌入自定义按钮?

ios - 带有 AutoDimension 的 UITableViewCell 中的 UITableView

ios - 一起使用 Nib 和 Storyboard : connect the nib's button target/action to a controller from the storyboard

ios - Swift 中 UIViewcontroller 的实例

ios - 如何在将 UIView 制作成图像之前正确布局它

ios - Xcode Storyboard屏幕类型影响模拟器内的布局

ios - Storyboard中的自定义 UIView 不显示 subview