问题 添加,重用和删除NSLayoutAnchors


所以我有一个 容器 视图(停靠在屏幕边缘)和a 儿童 认为它应该滑入和滑出它。

func slideOut() {
    UIView.animateWithDuration(Double(0.5), animations: {
        self.container.bottomAnchor
               .constraintEqualToAnchor(self.child.bottomAnchor).active = false
        self.view.layoutIfNeeded()
    })
}

func slideIn() {
    UIView.animateWithDuration(Double(0.5), animations: {
        self.container.bottomAnchor
               .constraintEqualToAnchor(self.child.bottomAnchor).active = true
        self.view.layoutIfNeeded()
    })
    print("numConstraints: \(container.constraints.count)")
}

slideIn() 动画很好,就像它应该的那样。问题是我不知道该怎么办 slideOut() 动画。如果我只是停用了 NSLayoutConstraint 如上所述,没有任何反应。如果相反,我尝试:

self.container.bottomAnchor
       .constraintEqualToAnchor(self.child.topAnchor).active = true

然后有一个关于无法同时满足约束的警告  视觉上没有任何事 而且,每当我做一个 NSLayoutConstraint 活跃,约束的数量(print(container.constraints.count))增加,这不是一件好事。

所以我的问题是:

  1. 我该怎么做呢? slideIn() 这种情况下的动画?
  2. 如何在重复动画的情况下重用现有约束,以便约束的数量不会累加?

1387
2018-05-01 21:00


起源



答案:


constraintEqualToAnchor method创建一个新约束。 所以当你打电话的时候 self.container.bottomAnchor.constraintEqualToAnchor(self.child.bottomAnchor) 在滑出功能中,你没有使用你在中添加的约束 slideIn 方法。

要实现所需的滑出动画,您必须保持对先前约束的引用。我不确定设置的效果是什么 .active 约束的属性将在滑出功能中,因为我不知道您的视图层次结构是如何设置的。 但是重用约束的一种方法是将它作为VC中的var属性:

lazy var bottomConstraint:NSLayoutConstraint = self.container.bottomAnchor
        .constraintEqualToAnchor(self.child.bottomAnchor)

func slideOut() {
    UIView.animateWithDuration(Double(0.5), animations: {
        self.bottomConstraint.active = false
        self.view.layoutIfNeeded()
    })
}

func slideIn() {
    UIView.animateWithDuration(Double(0.5), animations: {
        self.bottomConstraint.active = true
        self.view.layoutIfNeeded()
    })
    print("numConstraints: \(container.constraints.count)")
}

来自Apple Docs:

激活或取消激活约束会调用addConstraint:和removeConstraint:在视图上,该视图是此约束管理的项目的最近共同祖先。

因此,为什么要增加约束数量的原因是因为您不断创建新约束并通过设置添加它们 active 为真。


12
2018-05-01 21:22



我试图通过使用锚更新其最新的子视图底部约束来更改UIScrollView contentSize。停用,更改和重新激活它完成了工作。感谢您的回答,因为如果没有它,很难猜测该做什么。 - Skoua


答案:


constraintEqualToAnchor method创建一个新约束。 所以当你打电话的时候 self.container.bottomAnchor.constraintEqualToAnchor(self.child.bottomAnchor) 在滑出功能中,你没有使用你在中添加的约束 slideIn 方法。

要实现所需的滑出动画,您必须保持对先前约束的引用。我不确定设置的效果是什么 .active 约束的属性将在滑出功能中,因为我不知道您的视图层次结构是如何设置的。 但是重用约束的一种方法是将它作为VC中的var属性:

lazy var bottomConstraint:NSLayoutConstraint = self.container.bottomAnchor
        .constraintEqualToAnchor(self.child.bottomAnchor)

func slideOut() {
    UIView.animateWithDuration(Double(0.5), animations: {
        self.bottomConstraint.active = false
        self.view.layoutIfNeeded()
    })
}

func slideIn() {
    UIView.animateWithDuration(Double(0.5), animations: {
        self.bottomConstraint.active = true
        self.view.layoutIfNeeded()
    })
    print("numConstraints: \(container.constraints.count)")
}

来自Apple Docs:

激活或取消激活约束会调用addConstraint:和removeConstraint:在视图上,该视图是此约束管理的项目的最近共同祖先。

因此,为什么要增加约束数量的原因是因为您不断创建新约束并通过设置添加它们 active 为真。


12
2018-05-01 21:22



我试图通过使用锚更新其最新的子视图底部约束来更改UIScrollView contentSize。停用,更改和重新激活它完成了工作。感谢您的回答,因为如果没有它,很难猜测该做什么。 - Skoua