如何动态更新约束?

时间:2017-07-31 15:01:53

标签: ios swift nslayoutconstraint

我有三个UIButton,我已经创建了编程约束,在某些情况下我将UIButton中的一个删除为button.removeFromSuperview()&其余两个按钮将根据优先级设置约束。 问题是当我删除一个UIButton(buttonWink)然后从viewLifeCycle viewWillLayoutSubviews开始调用&应用程序崩溃在下面的行

 buttonWink.translatesAutoresizingMaskIntoConstraints = false

当然因为buttonWink已从superview中删除,但我们可以在设置约束之前检查

  if buttonWink != nil {
        buttonWink.translatesAutoresizingMaskIntoConstraints = false
      }

但是通过检查每个按钮的nil会使代码冗长,有没有办法做同样的事情?我真的很感谢朋友。

输出 -

enter image description here

这里我附上了我尝试过的完整代码。

import UIKit
class MasterViewController: UIViewController {
    @IBOutlet weak var buttonMessage : UIButton!
    @IBOutlet weak var buttonLike : UIButton!
    @IBOutlet weak var buttonWink : UIButton!
    @IBAction func tapsOnLike(_ sender: UIButton) {
        sender.removeFromSuperview()
    }
    @IBAction func tapsOnWink(_ sender: UIButton) {
        sender.removeFromSuperview()
    }
    @IBAction func tapsOnNextButton(){
        let vc = DetailViewController(nibName: "DetailViewController", bundle: nil)
        navigationController?.pushViewController(vc, animated: true)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
       setConstraints()
        navigationController?.isNavigationBarHidden = true
    }
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)
       // setConstraints()
    }
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        //setConstraints()
    }
    func setConstraints() {

        if buttonMessage != nil {
            buttonMessage?.translatesAutoresizingMaskIntoConstraints = false
        }
            buttonLike?.translatesAutoresizingMaskIntoConstraints = false
            buttonWink?.translatesAutoresizingMaskIntoConstraints = false

        //Constraints for Message button

        let leading = NSLayoutConstraint(item: buttonMessage, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 8)
        leading.isActive = true

        let trailingToSuperView = NSLayoutConstraint(item: buttonMessage, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: -8)

        trailingToSuperView.priority = 998
        trailingToSuperView.isActive = true

        let bottomToSuperView = NSLayoutConstraint(item: buttonMessage, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: -8)
        bottomToSuperView.isActive = true


        let trailingToWink = NSLayoutConstraint(item: buttonMessage, attribute: .trailing, relatedBy: .equal, toItem: buttonWink, attribute: .leading, multiplier: 1, constant: -8)
        trailingToWink.priority = 999
        trailingToWink.isActive = true

        let leadingToLike = NSLayoutConstraint(item: buttonMessage, attribute: .trailing, relatedBy: .equal, toItem: buttonLike, attribute: .leading, multiplier: 1.0, constant: -8)
        leadingToLike.isActive = true

        let alignBottomToWink = NSLayoutConstraint(item: buttonMessage, attribute: .bottom, relatedBy: .equal, toItem: buttonWink, attribute: .bottom, multiplier: 1, constant: 0)
        alignBottomToWink.isActive = true

        let alignBottomToLike = NSLayoutConstraint(item: buttonMessage, attribute: .bottom, relatedBy: .equal, toItem: buttonLike, attribute: .bottom, multiplier: 1, constant: 0)
        alignBottomToLike.isActive = true


        let equalWidthToWink = NSLayoutConstraint(item: buttonMessage, attribute: .width, relatedBy: .equal, toItem: buttonWink, attribute: .width, multiplier: 1, constant: 0)
        equalWidthToWink.isActive = true


        let equalWidthToLike = NSLayoutConstraint(item: buttonMessage, attribute: .width, relatedBy: .equal, toItem: buttonLike, attribute: .width, multiplier: 1, constant: 0)
        equalWidthToLike.isActive = true

        //Constraints for like button
        let trailingLikeToSuperView = NSLayoutConstraint(item: buttonLike, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: -8)
        trailingLikeToSuperView.priority = 999
        trailingLikeToSuperView.isActive = true
        let leadingToWink = NSLayoutConstraint(item: buttonLike, attribute: .trailing, relatedBy: .equal, toItem: buttonWink, attribute: .leading, multiplier: 1.0, constant: -8)
        leadingToWink.isActive = true


        //Constraints for Wink button
        let trailingWinkToSuperView = NSLayoutConstraint(item: buttonWink, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: -8)
        trailingWinkToSuperView.isActive = true

    }

}

3 个答案:

答案 0 :(得分:4)

仅供参考 -

只需使用堆栈视图即可。

这非常容易:这就是为什么Apple最近几年前添加了一个堆栈概念。

答案 1 :(得分:1)

我刚刚添加了UIStackView&这很容易 在水平堆叠视图中添加了三个按钮,具有8个点间距&添加了三个约束来将视图堆叠为leadingtrailing& bottomsuperview

enter image description here

@IBOutlet weak var stackView: UIStackView!
@IBAction func tapsOnLikeInStack(_ sender: UIButton) {
    sender.isHidden = true
}
@IBAction func tapsOnWinkInStack(_ sender: UIButton) {
    sender.isHidden = true
}

func constraintsForStackView(){
    stackView?.translatesAutoresizingMaskIntoConstraints = false
    stackView.spacing = 8
    stackView.axis = .horizontal
    stackView.distribution = .fillEqually
    stackView.alignment = .fill

    let leading = NSLayoutConstraint(item: stackView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 8)
    leading.isActive = true
    let trailingToSuperView = NSLayoutConstraint(item: stackView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: -8)
    trailingToSuperView.isActive = true
    let bottomToSuperView = NSLayoutConstraint(item: stackView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: -120)
    bottomToSuperView.isActive = true
}

答案 2 :(得分:0)

至于您的viewWillLayoutSubviews代码将您的按钮放入要使用的数组中:

for btn in buttons {
    if (btn.superview != nil) {
        btn.translatesAutoresizingMaskIntoConstraints = false
    }
}

如果您想更改视图中仍然存在的按钮的约束,请在创建约束时为它们指定标识符:

for btn in buttons {
    if btn.superview != nil {
        btn.translatesAutoresizingMaskIntoConstraints = false
        for constraint in btn.constraints {
            switch constraint.identifier {
                case "winkBtnTrailing":
                    //do stuff like constraint = new layout constraint
                    //or constraint.firstItem = *new first Item to base trailing on*
                    break
                default: 
                    //don't do stuff?
                    break
            }
        }
    }
}

正如使用button.removeFromSuperview()的仅供参考,并未将该按钮设置为nil,只是将其从您在{/ 1}}上调用的视图中删除