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

Why isn't my UILabel subview of a UIView not displaying?

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

我终于硬着头皮从故事板转移到以编程方式创建的视图层次结构,但遇到了障碍。在视图控制器的 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)
  }

}

使用 "constraint helpers" 的部分问题...我们有时不知道到底发生了什么。

您的分机有这个:

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 顶部下方 Style.edgeMargin 点处看到您的标签...但是,这会改变您在其他任何地方使用的布局 anchorTop()