Ios 如果要在之后设置自动布局约束的动画,我必须如何修改UIView扩展?

Ios 如果要在之后设置自动布局约束的动画,我必须如何修改UIView扩展?,ios,swift,xcode,nslayoutconstraint,Ios,Swift,Xcode,Nslayoutconstraint,我做了一个UIView扩展来设置我的NSLayout锚。一切正常。但是,如果我想添加一个NSLayoutConstraint,以便之后可以设置约束动画,那么如何修改扩展 这是我目前的分机: extension UIView { func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?,

我做了一个
UIView
扩展来设置我的
NSLayout
锚。一切正常。但是,如果我想添加一个
NSLayoutConstraint
,以便之后可以设置约束动画,那么如何修改扩展

这是我目前的分机:

extension UIView {
    func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
        //translate the view's autoresizing mask into Auto Layout constraints
        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
        }

        if let leading = leading {
            leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
        }

        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
        }

        if let trailing = trailing {
            trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
        }

        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }

        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
    }
}
下面是扩展名的名称:

//feedViewButton constraints
feedViewButton.anchor(top: nil, leading: nil, bottom: view.safeAreaLayoutGuide.bottomAnchor, trailing: view.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 0, right: 25), size: .init(width: 50, height: 50))
更新

我想要这样的

var topAnchor: NSLayoutConstraint?

topAnchor = topAnchor.constraint(equaltTo: top, constant: padding.top)
topAnchor.isActive = true
然后像这样设置动画:

let animator = UIViewPropertyAnimator(duration: 1, curve: .easeOut) {
    topAnchor.constant = 20
}
animator.startAnimation()

只需尝试使用autolayout为其设置动画,因为约束尚未应用,因此它应该可以设置动画:

feedViewButton.anchor(top: nil, leading: nil, bottom: view.safeAreaLayoutGuide.bottomAnchor, trailing: view.trailingAnchor, padding: .init(top: 0, left: 0, bottom: 0, right: 25), size: .init(width: 50, height: 50))
feedViewButton.superview?.setNeedsLayout()
UIView.animate(withDuration: 0.2, delay: 0, options: [.allowUserInteraction], animations: {
    feedViewButton.superview?.layoutIfNeeded()
}, completion: nil)
更新

如果希望以后更改锚定上的常量以设置其他更改的动画,则必须保留对约束的引用,以便以后能够操纵它们:

enum ConstraintType {
    case top, leading, trailing, bottom, width, height
}

extension UIView {

    func anchor(top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) -> [ConstraintType : NSLayoutConstraint] {
        //translate the view's autoresizing mask into Auto Layout constraints
        translatesAutoresizingMaskIntoConstraints = false

        var constraints: [ConstraintType : NSLayoutConstraint] = [:]

        if let top = top {
            constraints[.top] = topAnchor.constraint(equalTo: top, constant: padding.top)
        }

        if let leading = leading {
            constraints[.leading] = leadingAnchor.constraint(equalTo: leading, constant: padding.left)
        }

        if let bottom = bottom {
            constraints[.bottom] = bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom)
        }

        if let trailing = trailing {
            constraints[.trailing] = trailingAnchor.constraint(equalTo: trailing, constant: -padding.right)
        }

        if size.width != 0 {
            constraints[.width] = widthAnchor.constraint(equalToConstant: size.width)
        }

        if size.height != 0 {
            constraints[.height] = heightAnchor.constraint(equalToConstant: size.height)
        }
        let constraintsArray = Array<NSLayoutConstraint>(constraints.values)
        NSLayoutConstraint.activate(constraintsArray)
        return constraints
    }
}

您只需在扩展上添加动画即可,因此对
锚定
的所有调用都将设置动画,而无需始终添加动画块

extension UIView {

    func anchor(animated: Bool, top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
        //translate the view's autoresizing mask into Auto Layout constraints
        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
        }

        if let leading = leading {
            leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
        }

        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
        }

        if let trailing = trailing {
            trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
        }

        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }

        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
        if animated {
            UIView.animate(withDuration: 0.2, delay: 0, options: [.allowUserInteraction], animations: {
                self.layoutIfNeeded()
            }, completion: nil)
        } else {
            self.layoutIfNeeded()
        }
    }
}

可以但是,如果实现了UIPangestureRecognitor,它还能工作吗?这样我就可以跟踪用户的手指移动了多远。@JoshSchärer在我添加的更新答案
中说。允许WUSERINTERACTION
以确保已启用交互。如果你想知道它是否仍然有效,你可以尝试它。我想它应该有效,但是有没有可能添加一个NSLayoutConstraint,然后将该约束设置为另一个常量?@JoshSchärer有,但我不知道这与你的问题有什么关系。我已经更新了我的问题。希望您现在能够理解我希望如何完成它。可以,但我并不希望所有按钮都设置动画。我更新了代码以设置可选动画,如果您需要默认值,只需在函数声明中添加默认值,如:animation:Bool=true
extension UIView {

    func anchor(animated: Bool, top: NSLayoutYAxisAnchor?, leading: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, trailing: NSLayoutXAxisAnchor?, padding: UIEdgeInsets = .zero, size: CGSize = .zero) {
        //translate the view's autoresizing mask into Auto Layout constraints
        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            topAnchor.constraint(equalTo: top, constant: padding.top).isActive = true
        }

        if let leading = leading {
            leadingAnchor.constraint(equalTo: leading, constant: padding.left).isActive = true
        }

        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -padding.bottom).isActive = true
        }

        if let trailing = trailing {
            trailingAnchor.constraint(equalTo: trailing, constant: -padding.right).isActive = true
        }

        if size.width != 0 {
            widthAnchor.constraint(equalToConstant: size.width).isActive = true
        }

        if size.height != 0 {
            heightAnchor.constraint(equalToConstant: size.height).isActive = true
        }
        if animated {
            UIView.animate(withDuration: 0.2, delay: 0, options: [.allowUserInteraction], animations: {
                self.layoutIfNeeded()
            }, completion: nil)
        } else {
            self.layoutIfNeeded()
        }
    }
}