感觉这个问题的一些变体一定被问过,也被回答过,但我找不到它。
我终于咬紧牙关,从故事板转向以编程方式创建的视图层次结构,但遇到了一个障碍。 在视图控制器的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)
}
}
使用 "约束助手 "的部分问题......我们有时不知道到底发生了什么。
你的扩展有这个功能。
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
}
你会看到你的标签,在 Style.edgeMargin
pts低于managedView的顶部......但是,这将改变你的布局,你在其他任何地方使用的 anchorTop()
.