Swift Update Constraint

后端 未结 3 1051
逝去的感伤
逝去的感伤 2021-01-04 20:01

I added the constraint to the buttons created in my UIView

func CreateButtonWithIndex(index:Int) {

    newButton.setTranslatesAutoresizingMaskI         


        
相关标签:
3条回答
  • 2021-01-04 20:41

    The issue is that you're adding a new constraint that conflicts with the existing constraint.

    You have a few options:

    1. Effective in iOS 8, you can set the active property to false for a constraint before you add a new constraint.

    2. In iOS versions prior to 8, you would want to remove the old constraints before adding new constraints.

    3. Ideally, it's best to not have to activate/deactivate (or, worse, add and remove) constraints, but rather just modify the constant property of a single constraint. For example in Swift 3/4:

      class ViewController: UIViewController {
      
          private var xConstraint: NSLayoutConstraint!
          private var yConstraint: NSLayoutConstraint!
      
          override func viewDidLoad() {
              super.viewDidLoad()
      
              let label = UILabel()
              label.text = "x"
              label.translatesAutoresizingMaskIntoConstraints = false
              view.addSubview(label)
      
              // I don't really need to save references to these, so these are local variables
      
              let widthConstraint = label.widthAnchor.constraint(equalToConstant: 50)
              let heightConstraint = label.heightAnchor.constraint(equalToConstant: 50)
      
              // but since I'll be modifying these later, these are class properties
      
              xConstraint = label.centerXAnchor.constraint(equalTo: view.centerXAnchor)
              yConstraint = label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
      
              NSLayoutConstraint.activate([widthConstraint, heightConstraint, xConstraint, yConstraint])
      
              let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))
              view.addGestureRecognizer(pan)
          }
      
          private var originalCenter: CGPoint!
      
          @objc func handlePan(_ gesture: UIPanGestureRecognizer) {
              if gesture.state == .began {
                  originalCenter = CGPoint(x: xConstraint.constant, y: yConstraint.constant)
              }
      
              let translation = gesture.translation(in: gesture.view!)
      
              xConstraint.constant = originalCenter.x + translation.x
              yConstraint.constant = originalCenter.y + translation.y
          }
      
      }
      

      When the desired effect can be achieved by modifying the constant of the constraint, that's generally best.

    For Swift 2 syntax, see previous revision of this answer.

    0 讨论(0)
  • 2021-01-04 20:50

    Looks like you are just adding more and more constraint. You can't do that because they obviously conflict with each other. You are basically saying "put the view at position x = 1, x = 2, x = 3, x = 4 and x = 5".

    You have to remove the old constraints. You have two options to do that.

    1. Save the constraints in an array, and remove these constraints from the view before adding new ones.

    2. Or you keep a reference to the constraints that change and adjust their properties.

    Since your constraints just differ in the constant value you should go for option 2.

    Make newButtonConstraintX and newButtonConstraintY a variable of the viewController.

    e.g.

    class ViewController: UIViewController {
        var newButtonConstraintX: NSLayoutConstraint!
        var newButtonConstraintY: NSLayoutConstraint!
    
    
        func CreateButtonWithIndex(index:Int) {
    
            newButtonConstraintX = NSLayoutConstraint(item: newButton, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: CGFloat(riga))
    
            newButtonConstraintY = NSLayoutConstraint(item: newButton, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: CGFloat(colonna))
    
            /* ... */
        }
    
        func pan(rec:UIPanGestureRecognizer) {  
            /* ... */
            newButtonConstraintX.constant = line
            newButtonConstraintY.constant = column
            button.layoutIfNeeded()
        }
    
    0 讨论(0)
  • 2021-01-04 21:06

    Update Rob's Answer to Swift 3:

    class ViewController: UIViewController {
    
        private var xConstraint: NSLayoutConstraint!
        private var yConstraint: NSLayoutConstraint!
    
        override func viewDidLoad() {
        super.viewDidLoad()
    
        let label = UILabel()
        label.text = "x"
        label.setTranslatesAutoresizingMaskIntoConstraints(false)
        view.addSubview(label)
    
        // I don't really need to save references to these, so these are local variables
    
    
        let widthConstraint = NSLayoutConstraint(item: drugToDrugView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 50)
        let heightConstraint = NSLayoutConstraint(item: drugToDrugView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 50)
    
        // but since I'll be modifying these later, these are class properties
    
        xConstraint = NSLayoutConstraint(item: drugToDrugView, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0)
        yConstraint = NSLayoutConstraint(item: drugToDrugView, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1.0, constant: 0)
    
        drugToDrugView.addConstraints([widthConstraint, heightConstraint, xConstraint, yConstraint])
    
        let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
        view.addGestureRecognizer(pan)
    
     }
    
     private var originalCenter: CGPoint!
    
     func handlePan(gesture: UIPanGestureRecognizer) {
        if gesture.state == .began {
            originalCenter = CGPoint(x: xConstraint.constant, y: yConstraint.constant)
        }
    
        let translation = gesture.translation(in: gesture.view!)
    
        xConstraint.constant = originalCenter.x + translation.x
        yConstraint.constant = originalCenter.y + translation.y
        view.setNeedsLayout()
    }
    
    0 讨论(0)
提交回复
热议问题