2015-01-09 22 views
8

tôi đã thêm các hạn chế đối với các nút được tạo ra trong tôi UIViewSwift Cập nhật Hạn chế

func CreateButtonWithIndex(index:Int) { 

    newButton.setTranslatesAutoresizingMaskIntoConstraints(false) 

    self.view.addSubview(newButton) 

    let newButtonConstraintL = NSLayoutConstraint(item: newButton, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 50) 
    let newButtonConstraintH = NSLayoutConstraint(item: newButton, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 50) 
    var newButtonConstraintX = NSLayoutConstraint(item: newButton, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: CGFloat(riga)) 
    var newButtonConstraintY = NSLayoutConstraint(item: newButton, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: CGFloat(colonna)) 

    view.addConstraints([newButtonConstraintX,newButtonConstraintY,newButtonConstraintH,newButtonConstraintL]) 

    var pan = UIPanGestureRecognizer(target:self, action:"pan:") 
    pan.maximumNumberOfTouches = 2 
    pan.minimumNumberOfTouches = 1 
    newButton.addGestureRecognizer(pan) 
} 

func pan(rec:UIPanGestureRecognizer) { 
    case .Ended: 
     if let subview = selectedView { 
      if let button = rec.view as? UIButton { 
       if let title = button.titleForState(.Normal){ 
        button.setTranslatesAutoresizingMaskIntoConstraints(false) 
        let line = Float(p.x % snapX) 
        let column = Float(p.x % snapY) 
        let constraintL = NSLayoutConstraint(item: button, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 50) 
        let constraintH = NSLayoutConstraint(item: button, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 50) 
        var constraint2 = NSLayoutConstraint(item: button, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: CGFloat(line)) 
        var constraint3 = NSLayoutConstraint(item: button, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: CGFloat(column)) 

        view.addConstraints([constraint2,constraint3,constraintL.constraintH]) 
       } 
      } 
     } 
} 

Trong dự án Mỹ người dùng của tôi có thể di chuyển các nút và sau đó tôi cố gắng thêm khó khăn hơn đối với các nút công nhận nhưng tôi chỉ nhận được một bất tận lỗi khó khăn

"<NSLayoutConstraint:0x7f8e5a4e9450 UIButton:0x7f8e5a644f60'Button6'.centerX == UIView:0x7f8e5a648bc0.centerX - 120>", 
    "<NSLayoutConstraint:0x7f8e5a5be040 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7f8e5a648bc0(736)]>", 
    "<NSAutoresizingMaskLayoutConstraint:0x7f8e5a5be1f0 h=-&- v=-&- 'UIView-Encapsulated-Layout-Left' H:|-(0)-[UIView:0x7f8e5a648bc0] (Names: '|':UITransitionView:0x7f8e5a5a8190)>", 
    "<NSAutoresizingMaskLayoutConstraint:0x7f8e5a5b53b0 h=--& v=--& UIButton:0x7f8e5a644f60'Button6'.midX == + 200>" 

sẽ cố gắng để khôi phục lại bằng cách phá vỡ chế

"<NSLayoutConstraint:0x7f8e5a4e9450 UIButton:0x7f8e5a644f60'Button6'.centerX == UIView:0x7f8e5a648bc0.centerX - 120>" 

"<NSLayoutConstraint:0x7f8e5a4e9510 UIButton:0x7f8e5a644f60'Button6'.centerY == UIView:0x7f8e5a648bc0.centerY - 40>", 
"<NSLayoutConstraint:0x7f8e5a5be1a0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7f8e5a648bc0(414)]>", 
"<NSAutoresizingMaskLayoutConstraint:0x7f8e5a5be240 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' V:|-(0)-[UIView:0x7f8e5a648bc0] (Names: '|':UITransitionView:0x7f8e5a5a8190)>", 
"<NSAutoresizingMaskLayoutConstraint:0x7f8e5a5b82d0 h=--& v=--& UIButton:0x7f8e5a644f60'Button6'.midY == + 189>" 

sẽ cố gắng để khôi phục lại bằng cách phá vỡ chế

<NSLayoutConstraint:0x7f8e5a4e9510 UIButton:0x7f8e5a644f60'Button6'.centerY == UIView:0x7f8e5a648bc0.centerY - 40> 

... Tôi nên cập nhật newButtonConstraintX/Y nhưng tôi không hiểu làm thế nào tôi có thể làm điều này?

Trả lời

15

Vấn đề là bạn đang thêm một ràng buộc mới xung đột với ràng buộc hiện tại.

Bạn có một vài lựa chọn:

  1. hiệu quả trong iOS 8, bạn có thể thiết lập các thuộc tính để activefalse cho một hạn chế trước khi bạn thêm một ràng buộc mới.

  2. Trong các phiên bản iOS trước 8, bạn sẽ muốn xóa các ràng buộc cũ trước khi thêm các ràng buộc mới.

  3. Lý tưởng nhất, tốt nhất là không phải kích hoạt/hủy kích hoạt (hoặc, tệ hơn, thêm và loại bỏ) các ràng buộc, mà chỉ sửa đổi thuộc tính constant của một ràng buộc duy nhất. Ví dụ: trong 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 
        } 
    
    } 
    

    Khi hiệu ứng mong muốn có thể đạt được bằng cách sửa đổi constant của ràng buộc, nói chung là tốt nhất.

Đối với cú pháp Swift 2, xem previous revision of this answer. Trả lời

+0

Hi @ Rob, tôi đang sử dụng phương pháp tương tự. Tôi đã thêm ràng buộc lập trình và bây giờ cập nhật hằng số, nhưng nó không cập nhật xem tại. – ChanWarde

+0

Tôi đã thử nó với các ràng buộc kết nối từ bảng phân cảnh và thay đổi các hằng số của nó từ IBOutlet đang hoạt động tốt. – ChanWarde

0

Có vẻ như bạn vừa thêm nhiều hạn chế hơn. Bạn không thể làm điều đó bởi vì họ rõ ràng là xung đột với nhau. Về cơ bản, bạn nói "đặt chế độ xem ở vị trí x = 1, x = 2, x = 3, x = 4 và x = 5".

Bạn phải xóa các ràng buộc cũ. Bạn có hai lựa chọn để làm điều đó.

  1. Lưu các ràng buộc trong một mảng và xóa các ràng buộc này khỏi chế độ xem trước khi thêm các điểm mới.

  2. Hoặc bạn giữ một tham chiếu đến các ràng buộc thay đổi và điều chỉnh các thuộc tính của chúng.

Kể từ khó khăn của bạn chỉ khác nhau về giá trị không đổi, bạn nên đi cho tùy chọn 2.

Hãy newButtonConstraintXnewButtonConstraintY một biến của viewController.

ví dụ:

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

Cập nhật Rob để 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

Không cập nhật khung xem. – ChanWarde

Các vấn đề liên quan