如果我有 IBOutlet 进行约束,复杂 UIView 的布局会有所不同

Posted

技术标签:

【中文标题】如果我有 IBOutlet 进行约束,复杂 UIView 的布局会有所不同【英文标题】:Complex UIView lays out differently if I have IBOutlet for constraint 【发布时间】:2018-12-16 23:45:24 【问题描述】:

在下面的屏幕截图中,我所做的唯一更改是为约束连接一个 IBOutlet。未连接,屏幕布局正确。已连接,屏幕布局不正确。我以前从未见过这种情况,也不知道该如何解决。我需要能够修改约束的常量值,以便根据特定项目的存在或不存在来调整子视图的大小。

IBOutlet 声明为:

@IBOutlet weak var tabContentBottomConstraint: NSLayoutConstraint!

到目前为止,我还没有实现任何读取或修改此约束的代码。我将它添加到我的视图控制器以准备使用它,但没有更进一步,因为当我在添加 IBOutlet 后运行代码时,视图大小不正确。我添加和删除了好几次,结果都是一样的。

这是连接插座之前视图尺寸的调试器信息:

这是连接 IBOutlet 后的调试器信息,没有任何其他代码更改:

y 偏移的差异很大,会将视图推离屏幕。正如我上面所说,没有代码读取或写入该 IBOutlet。

rolePageDrawerView是约束中的item2,item1是视图控制器的view.safeAreaLayoutGuide。 rolePageDrawerView 在 vi​​ew.safeAreaLayoutGuide 的子视图中嵌入了 3 层。

【问题讨论】:

出于好奇,如果您删除 weak 关键字会发生什么?如果约束在代码中的某处被停用,弱变量不会阻止它被释放。 @Samantha 它没有被释放。您可以在我的屏幕截图中看到该插座仍处于填充状态。此外,我确实删除了weak并重新运行,但它的大小仍然不正确。 我无法从新项目和您的描述中重现该问题。我创建了一个具有上面列出的相同约束、框架和原点的视图。我将高度和宽度限制设置为等于您提供的框架。我看到的唯一可能不同的是您对相关视图的自动调整大小掩码。我建议您将您的视图(及其子视图)抽象到一个新项目中以进一步隔离问题。 @RLoniello 有问题的视图非常复杂和专有,所以我在这里分享的内容有限。我的怀疑是 rolePageDrawerView 在视图内部有几个层次并绑定到外部视图安全区域布局指南与它有关。如果有机会,我会尝试在一个更简单的项目中重现它并提交错误报告。目前,我有一个解决办法,并且会接受它,这样我就可以继续我的项目。 【参考方案1】:

我找到了一种解决这种奇怪行为的方法,方法是使用以下代码以编程方式搜索约束:

    guard let tabContentBottomConstraint = view.constraints.filter( $0.secondItem! as! NSObject == rolePageTabContentView ).first else 
        fatalError("unable to find the constraint for drawer sizing")
    
    self.tabContentBottomConstraint = tabContentBottomConstraint

我将约束保留为弱引用,即使它不再被注入,因为视图本身将具有对它的引用以使其保持活动状态。它有效。

但是,我将问题留待更好的解决方案。上面的搜索是非常脆弱的一些未来的布局变化。如果框架在不破坏布局的情况下注入约束会更好。仍然愿意寻求更好的解决方案。

【讨论】:

以上是关于如果我有 IBOutlet 进行约束,复杂 UIView 的布局会有所不同的主要内容,如果未能解决你的问题,请参考以下文章

如果不允许约束,如何移动 CAGradientLayer 及其父 UIView 容器?

IBOutlet 用于约束并以编程方式将其连接到 UIButton

如何在没有 IBOutlet 或标识符的情况下从 Storyboard 更新约束?

拦截/以编程方式设置 IBOutlet 属性

如何在不制作 IBOutlet 的情况下以编程方式在 Swift 中为 UIView 高度约束设置动画?

在 UIView 内对 UITableView 设置约束