为啥我的 UIView 的 UILabel 子视图不显示?

Posted

技术标签:

【中文标题】为啥我的 UIView 的 UILabel 子视图不显示?【英文标题】:Why isn't my UILabel subview of a UIView not displaying?为什么我的 UIView 的 UILabel 子视图不显示? 【发布时间】:2020-05-14 13:13:33 【问题描述】:

感觉这个问题的一些变体肯定已经被问到并得到了回答,但我找不到它。

我终于硬着头皮从故事板转移到以编程方式创建的视图层次结构,但遇到了障碍。在视图控制器的 viewDidLoad() 中,我成功添加了一个子视图,我在变量 managedView 中保留了对它的引用。紧接着(在同一个 viewDidLoad 中),我试图添加一个 UILabel 作为 managedView 的子视图。但是标签没有出现。没有错误信息,没有失败,没有标签……

我已使用视图调试器并确认标签不存在但不可见或不在屏幕上的情况。它不在视图层次结构中。

我错过了什么?

这是 viewDidLoad 中的代码

  override func viewDidLoad()
  
    super.viewDidLoad()

    view.backgroundColor = .clear

    managedView = UIView()
    view.addSubview(managedView)
    managedView.translatesAutoresizingMaskIntoConstraints = false
    managedView.backgroundColor = .systemBackground
    managedView.layer.cornerRadius = 10
    managedView.layer.masksToBounds = true
    managedView.layer.borderColor = UIColor.gray.cgColor
    managedView.layer.borderWidth = 1.0
    managedView.alignCenter(to: view)
    managedView.minSize(width:200.0, height:200.0)

    let titleView:UILabel =
    
      let v = UILabel()
      v.translatesAutoresizingMaskIntoConstraints = false
      v.text = title ?? "???"
      v.font = Style.titleFont
      v.backgroundColor = .systemYellow
      v.textColor = UIColor.label
      return v
    ()
    managedView.addSubview(titleView)
    titleView.anchorTop(to: managedView,offset: Style.edgeMargin)
    titleView.constrainSize(width:150.0, height:15.0)
    titleView.alignCenterX(to: managedView)
  

请注意,我扩展了 UIView 以提供更简单的命名自动布局约束方法。下面是上面用到的约束方法的代码:

extension UIView

  ...

  func alignCenterX(to otherView:UIView, offset:CGFloat = 0.0)
  
    self.centerXAnchor.constraint(equalTo: otherView.centerXAnchor, constant: offset).isActive = true
  

  ...

  func anchorTop(to otherView:UIView, offset:CGFloat = 0.0)
  
    self.topAnchor.constraint(equalTo: otherView.bottomAnchor, constant: offset).isActive = true
  

  ...

  func alignCenterY(to otherView:UIView, offset:CGFloat = 0.0)
  
    self.centerYAnchor.constraint(equalTo: otherView.centerYAnchor, constant: offset).isActive = true
  

  ...

  func constrainWidth(_ width:CGFloat)
  
    self.widthAnchor.constraint(equalToConstant: width).isActive = true
  
  func constrainHeight(_ height:CGFloat)
  
    self.heightAnchor.constraint(equalToConstant: height).isActive = true
  

  ...

  func minWidth(_ width:CGFloat)
  
    self.widthAnchor.constraint(greaterThanOrEqualToConstant: width).isActive = true
  

  func minHeight(_ height:CGFloat)
  
    self.heightAnchor.constraint(greaterThanOrEqualToConstant: height).isActive = true
  

  ...

  func alignCenter(to otherView:UIView)
  
    alignCenterY(to: otherView)
    alignCenterX(to: otherView)
  

  func minSize(width:CGFloat,height:CGFloat)
  
    self.minWidth(width)
    self.minHeight(height)
  


【问题讨论】:

constrainSize 在哪里? 除了minSize之外,您是否对managedView添加了任何约束? Doh... 问这个问题时不小心把它删掉了。 constrainSize() 只是对 constrainWidth() 和 constrainHeight() 的包装 alignCenter(to:view) 添加约束以将托管视图的 centerXAnchor 和 centerYanchor 分别等同于视图的 centerXAnchor 和 centerYanchor。 我明白了...期待:) ...除了 minSize 之外,您是否向 managedView 添加了任何约束?这个呢? 【参考方案1】:

使用“约束助手”的部分问题......我们有时不知道到底发生了什么。

你的扩展有这个:

func anchorTop(to otherView:UIView, offset:CGFloat = 0.0)

    self.topAnchor.constraint(equalTo: otherView.bottomAnchor, constant: offset).isActive = true

你在打电话

titleView.anchorTop(to: managedView,offset: Style.edgeMargin)

这意味着:

set the TOP of titleLabel to the BOTTOM of managedView + Style.edgeMargin

如果您将anchorTop 更改为:

func anchorTop(to otherView:UIView, offset:CGFloat = 0.0)

    self.topAnchor.constraint(equalTo: otherView.topAnchor, constant: offset).isActive = true

您将在 managedView 的 TOP 下方的 Style.edgeMargin pts 处看到您的标签...但是,这会改变您使用 anchorTop() 的其他任何地方的布局。

【讨论】:

谢谢!!!就是这样。我的意思是使用 alignTop() 函数而不是 anchorTop()... 这完全符合您的建议。 @MikeMayer67 - 顺便...其superview的范围。此外,您的 minSize() 助手会留下歧义。 我知道这种歧义。设置不完整。最后,在完全填充 managedView 并设置所有约束后,我将删除 minSize 约束,以便视图适合其内容。我临时添加了 minSize 来演示这个问题。另外,我决定将anchorTop、anchorBottom、anchorLeft和anchorRight方法重命名为attachTop、attachBottom等,以避免重复同样的布局错误的机会。

以上是关于为啥我的 UIView 的 UILabel 子视图不显示?的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS中的UIView子视图下方插入UILabel

UIView 不根据子视图调整宽度?

将 UILabel 粘贴到 UIView 或 UIImageView

如何设置 UIView 高度等于两个子视图 UILabel 的最大值?

将 UIView 调整为其 UILabel 子视图的大小

如何设置UIView高度等于两个子视图UILabel的最大值?