取消激活将它们链接在一起的 2 个对象之间的约束

De activate constraints between 2 objects linking them together

我的 swift 代码,您可以在下面的 gif 中看到。让用户 select 图像视图之一,然后使用滑块增加或减小该图像视图的大小。问题是当图像视图移动时,另一个图像视图跟随它,这是不应该发生的。因此,应该在代码第一次运行时但在其中一个图像视图 selected 之后设置约束。将它们链接在一起的约束应该被停用。导致这个的一行是

** greenMove.leadingAnchor.constraint(等于:view.leadingAnchor,常量:0),**

import UIKit

class ViewController: UIViewController {



    var image1Width: NSLayoutConstraint!
    var image1Height: NSLayoutConstraint!
    var image1Width2: NSLayoutConstraint!
    var image1Height2: NSLayoutConstraint!
    var greenMove = UIImageView()
    var slider = UISlider()
    var blueMove = UIImageView()
    var existingTransition : CGAffineTransform?
    var clock = Int()
    var currentView: UIView?
    var g2 = UIPanGestureRecognizer()
    var g3 = UIPanGestureRecognizer()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        greenMove.isUserInteractionEnabled = true
        blueMove.isUserInteractionEnabled = true

        g2 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g1Method))
        greenMove.addGestureRecognizer(g2)
        g3 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g2Method))
        blueMove.addGestureRecognizer(g3)

        greenMove.backgroundColor = .systemGreen

        blueMove.backgroundColor = .blue


        [greenMove,slider,blueMove].forEach {

            view.addSubview([=10=])
            [=10=].translatesAutoresizingMaskIntoConstraints = false

        }


        //image11
        image1Width =  greenMove.widthAnchor.constraint(equalTo:  view.widthAnchor ,multiplier:  0.2)
        image1Height =  greenMove.heightAnchor.constraint(equalTo:  view.heightAnchor ,multiplier:  0.20)

        //image12
        image1Width2 =  blueMove.widthAnchor.constraint(equalTo:  view.widthAnchor ,multiplier:  0.2)
        image1Height2 =  blueMove.heightAnchor.constraint(equalTo:  view.heightAnchor ,multiplier:  0.20)



        NSLayoutConstraint.activate([

            greenMove.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
            image1Width,
            image1Height,
            greenMove.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant :0),


            blueMove.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
            image1Width2,
            image1Height2,
            blueMove.leadingAnchor.constraint(equalTo: greenMove.trailingAnchor, constant :0)

        ])








        slider.addTarget(self, action: #selector(hhh), for: .allEvents)

    }

    override func viewDidLayoutSubviews() {
        NSLayoutConstraint.activate ([




            slider.topAnchor.constraint(equalTo: view.topAnchor, constant : greenMove.bounds.height),
            slider.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.20, constant: 0),
            slider.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.20, constant: 0),
            slider.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),


        ])
    }
    @objc func handleTapGestured(_ gesture: UIPanGestureRecognizer) {
        currentView = gesture.view
    }

    @objc func g1Method(_ sender: UIPanGestureRecognizer){
        clock = 1
        let subview = greenMove
        guard let child = sender.view else{return}
        let transitionPoint = sender.translation(in: self.view)
        let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
        switch sender.state {

        case .ended,.cancelled:// on End
            if let existing = existingTransition{
                self.existingTransition = newTransition.concatenating(existing)
            }else{
                self.existingTransition = newTransition
            }
        default://on change and other states
            if let existing = existingTransition{
                child.transform = newTransition
                    .concatenating(existing)
            }else{
                child.transform = newTransition
            }
        }
        self.view.layoutIfNeeded()


        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
        subview.addGestureRecognizer(tapGesture)


    }
    @objc func g2Method(_ sender: UIPanGestureRecognizer){
        clock = 2
        let subview = blueMove
        guard let child = sender.view else{return}
        let transitionPoint = sender.translation(in: self.view)
        let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)
        switch sender.state {

        case .ended,.cancelled:// on End
            if let existing = existingTransition{
                self.existingTransition = newTransition.concatenating(existing)
            }else{
                self.existingTransition = newTransition
            }
        default://on change and other states
            if let existing = existingTransition{
                child.transform = newTransition
                    .concatenating(existing)
            }else{
                child.transform = newTransition
            }
        }
        self.view.layoutIfNeeded()


        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
        subview.addGestureRecognizer(tapGesture)


    }
    @objc func hhh() {

        if clock ==  1 {
            image1Width.constant = CGFloat(slider.value) * view.frame.size.width * 0.25
            image1Height.constant = CGFloat(slider.value) * view.frame.size.height * 0.25
        }
        if clock  == 2 {

            image1Width2.constant = CGFloat(slider.value) * view.frame.size.width * 0.25
            image1Height2.constant = CGFloat(slider.value) * view.frame.size.height * 0.25
        }




    }

}

最好的方法是在安全区域前导和图像前导之间创建蓝图前导约束,而不是在两个图像之间创建前导约束,因为当您禁用两个图像之间的约束时,您会遇到错误,因为视图没有'不知道把图片放在哪里

您 运行 遇到的问题是因为您对两个视图都使用了一个变换,并连接了新的变换信息,当您尝试移动它时,该信息将应用于另一个视图。

对您发布的代码进行这些更改...

在 class 级别,创建单独的转换 "trackers":

// don't use this
//var existingTransition : CGAffineTransform?

// separate transforms for each "move view"
var blueTransition: CGAffineTransform?
var greenTransition: CGAffineTransform?

然后,在 g1Methodg2Method 中使用关联的转换:

@objc func g1Method(_ sender: UIPanGestureRecognizer){
    clock = 1
    let subview = greenMove
    guard let child = sender.view else{return}
    let transitionPoint = sender.translation(in: self.view)
    let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)

    // greenMove view must track its own CGAffineTransform

    switch sender.state {

    case .ended,.cancelled:// on End
        if let existing = greenTransition {
            greenTransition = newTransition.concatenating(existing)
        } else {
            greenTransition = newTransition
        }
        //if let existing = existingTransition{
        //  self.existingTransition = newTransition.concatenating(existing)
        //}else{
        //  self.existingTransition = newTransition
        //}
    default://on change and other states
        if let existing = greenTransition {
            child.transform = newTransition
                .concatenating(existing)
        } else {
            child.transform = newTransition
        }
        //if let existing = existingTransition{
        //  child.transform = newTransition
        //      .concatenating(existing)
        //}else{
        //  child.transform = newTransition
        //}
    }
    self.view.layoutIfNeeded()

    // move this to viewDidLoad(), otherwise you are adding ANOTHER recognizer each time this method is called
    //let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
    //subview.addGestureRecognizer(tapGesture)


}
@objc func g2Method(_ sender: UIPanGestureRecognizer){
    clock = 2
    let subview = blueMove
    guard let child = sender.view else{return}
    let transitionPoint = sender.translation(in: self.view)
    let newTransition = CGAffineTransform(translationX: transitionPoint.x, y: transitionPoint.y)

    // blueMove view must track its own CGAffineTransform

    switch sender.state {

    case .ended,.cancelled:// on End
        if let existing = blueTransition {
            blueTransition = newTransition.concatenating(existing)
        } else {
            blueTransition = newTransition
        }
        //if let existing = existingTransition{
        //  self.existingTransition = newTransition.concatenating(existing)
        //}else{
        //  self.existingTransition = newTransition
        //}
    default://on change and other states
        if let existing = blueTransition {
            child.transform = newTransition
                .concatenating(existing)
        } else {
            child.transform = newTransition
        }
        //if let existing = existingTransition{
        //  child.transform = newTransition
        //      .concatenating(existing)
        //}else{
        //  child.transform = newTransition
        //}
    }
    self.view.layoutIfNeeded()

    // move this to viewDidLoad(), otherwise you are adding ANOTHER recognizer each time this method is called
    //let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGestured(_:)))
    //subview.addGestureRecognizer(tapGesture)


}