Storyboard xib 实时视图在左上角呈现所有子视图

Posted

技术标签:

【中文标题】Storyboard xib 实时视图在左上角呈现所有子视图【英文标题】:Storyboard xib live view renders all subviews in top-left corner 【发布时间】:2021-02-10 18:52:59 【问题描述】:

我正在使用 XCode 12.1,我正在尝试创建一些可重用的 XIB,并希望在情节提要中呈现它们。我的问题是所有这些视图都将呈现在左上角,就像我加载的视图的框架是CGRect.zero 一样。故事板中的视图控制器如下所示:

我创建了一个UIView 的子类,它从.xib 动态加载视图:

import UIKit

@IBDesignable
class NibView: UIView 

    required init?(coder: NSCoder) 
        super.init(coder: coder)

        self.createNibView()
    

    override init(frame: CGRect) 
        super.init(frame: frame)

        self.createNibView()
    
    
    private func createNibView() 
        guard let view = loadFromNib() else  return 
        self.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(view)
        self.createConstraints(for: view)
        self.setNeedsLayout()
    
    
    private func loadFromNib() -> UIView? 
        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
        let view = nib.instantiate(withOwner: self, options: nil).first as? UIView
        view?.translatesAutoresizingMaskIntoConstraints = false
        return view
    
    
    private func createConstraints(for view: UIView) 
        NSLayoutConstraint.activate([
            self.topAnchor.constraint(equalTo: view.topAnchor),
            self.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            self.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            self.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
    


以及此视图的子类:

import UIKit

@IBDesignable
class RDTextField: NibView 
    
    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var errorLabel: UILabel!
    @IBOutlet weak var errorIcon: UIImageView!

与关联的xib:

在情节提要中,我添加了一个视图,为此我设置了此自定义视图的类,它是从带有情节提要的图像中选择的视图。

我也尝试过使用awakeAfter(using coder:),但没有更好的结果,我尝试使用自动调整大小掩码,它稍微好一点,因为它正确设置了原点,但它没有正确的大小。无论如何,我想使用translatesAutoresizingMaskIntoConstraints disabled 并使用我自己的约束。

我也尝试调试这些视图,但 XCode 不会附加到任何进程,并且我在 Console.app 中找不到日志。

注意:我有一个UIView 的扩展名IBDesignable,它可以帮助我设置边框颜色、宽度和半径。我试过禁用它,但没有任何结果。

注意 2:在运行时一切正常,但也非常需要情节提要中的实时视图。

有没有人遇到过这个问题或者知道如何解决这个问题?

【问题讨论】:

【参考方案1】:

Storyboard 对象的 root 视图始终使用自动调整大小蒙版。您的代码正在禁用它。

NibView 类中从 createNibView() 函数中删除一行

private func createNibView() 
    guard let view = loadFromNib() else  return 
    
    // don't do this!
    //self.translatesAutoresizingMaskIntoConstraints = false
    
    self.addSubview(view)
    self.createConstraints(for: view)
    self.setNeedsLayout()

应该可以的。

【讨论】:

谢谢您,先生!这工作得很好,你结束了我两天的噩梦。我确实尝试过使用自动调整大小的蒙版,但也许我在那里遇到了其他问题,使其无法正常工作。只是出于好奇:这实际上会在运行时生成 2 组约束吗? @VladRusu - 你甚至不需要考虑自动调整遮罩的大小。对您的所有 XIB 子视图使用正常的自动布局约束,并将您在 Storyboard 中添加的 RDTextField 视为您在 Storyboard 中添加的任何其他视图。

以上是关于Storyboard xib 实时视图在左上角呈现所有子视图的主要内容,如果未能解决你的问题,请参考以下文章

代码视图与StoryBoard.Xib文件视图的跳转

Xcode中不用Storyboard,用纯xib创建TabBar模式视图

将 Storyboard 和 xib 用于同一个视图控制器?

通过 xib 或 storyboard 将子视图添加到 UICollectionViewCell 的 contentView

Xcode 5 - iOS - 如何在没有 Storyboard 或 XIB 的情况下在 Xcode 中创建视图控制器以及如何将其配置为 AppDelegate 作为根视图

使用 Storyboard id iOS 以编程方式调用视图控制器