使用TopLayoutGuide限制制图

时间:2015-06-23 08:20:15

标签: ios swift constraints cartography

我有一个观点,我希望看起来像这样:

|---------------|
|               | <- navBar
|---------------|
|               | <- topView
|---------------|
|               |
|               |
|               |
|---------------|

我想要的一切就是将topView.top粘贴到navBar.bottom。我决定使用Cartography并实现以下代码(试图坚持使用MVC ofc):

在我的UIViewController子类中:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    aView?.topLayoutGuide = self.topLayoutGuide // where aView is my subclass of UIView, inserted in loadView method
}

在我的UIView子类中:

var topLayoutGuide: UILayoutSupport?

override func updateConstraints() {
    var constraint = NSLayoutConstraint?()
    layout(topView) { (topView) in
        constraint = topView.top == topView.superview!.top
    }
    topView.superview!.removeConstraint(constraint!)

    layout(topView) { topView in
        topView.top == topView.superview!.top + (self.topLayoutGuide?.length ?? 0)
        topView.height == 67
        topView.left == topView.superview!.left
        topView.width == topView.superview!.width
    }

    super.updateConstraints()
}

问题是我收到了以下日志,我不知道如何解决它:

Unable to simultaneously satisfy constraints.
[...]
(
    "<NSLayoutConstraint:0x7fe6a64e4800 V:|-(64)-[UIView:0x7fe6a6505d80]   (Names: '|':MyApp.MyView:0x7fe6a360d4c0 )>",
    "<NSLayoutConstraint:0x7fe6a3538a80 V:|-(0)-[UIView:0x7fe6a6505d80]   (Names: '|':MyApp.MyView:0x7fe6a360d4c0 )>"
)

似乎我需要一些帮助。怎么做得好?我不想在UIViewController中实施约束,我也不想使用Storyboards

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

一种解决方案:创建对该特定NSLayoutConstraint的引用,并更新其constant

var topLayoutConstraint: NSLayoutConstraint!

override func updateConstraints() { 
    layout(topView) { topView in
        topLayoutConstraint = topView.top == topView.superview!.top
        topView.height == 67
        topView.left == topView.superview!.left
        topView.width == topView.superview!.width
    }

    super.updateConstraints()
}

...然后,您可以像这样调整NSLayoutConstraint的常量:

topLayoutConstraint.constant = 50

唯一的问题是 - 您何时更新topLayoutConstraint?一种解决方案是创建协议MyViewInterface

protocol MyViewInterface: class {
    var topLayoutGuideLength: CGFloat { get set }
}

然后,在我们的UIView中,当topLayoutGuideLength属性发生变化时,我们会调整constant的{​​{1}}:

NSLayoutConstraint

最后,在我们public class MyView: UIView, MyViewInterface { public var topLayoutGuideLength: CGFloat = 0 { didSet { topLayoutConstraint.constant = topLayoutGuideLength } } } (我们UIViewController生活的地方):

topLayoutGuide

最终结果?每当我们public class myViewController: UIViewController { private var myView: MyView // ... public override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() myView.topLayoutGuideLength = topLayoutGuide.length } } 触发viewDidLayoutSubviews()时,我们的UIViewController myView属性就会更新,从而触发topLayoutGuideLength&#39的更改; s topLayoutConstraint

答案 1 :(得分:1)

另外缺少制图文档......

我在制图中将topLayoutGuideCartographybottomLayoutGuideCartography属性视为UIViewController扩展。使用它们可以在不覆盖viewDidLayoutSubviews

的情况下为您提供所需的输出

您只需使用此属性即可固定视图的顶部。

override func updateConstraints() { 
    layout(topView) { topView in
       topView.top == topLayoutGuideCartography
       topView.height == 67
       topView.left == topView.superview!.left
       topView.width == topView.superview!.width
    }

    super.updateConstraints()
}