Swift-UIPANGESTURE识别器在只希望选择顶层时选择所有层

Swift-UIPANGESTURE识别器在只希望选择顶层时选择所有层,swift,xcode,uiview,uipangesturerecognizer,uiview-hierarchy,Swift,Xcode,Uiview,Uipangesturerecognizer,Uiview Hierarchy,我有一个函数,它可以创建一条拖拽线,将两个按钮相互连接起来。这很好,但是如果一些按钮相互重叠,如果我在它们重叠的地方拖动,它将同时选择这两个按钮。我只想连接顶部的按钮 我认为问题在于sender.location选择顶部和底部的层。有没有办法告诉sender.location仅选择俯视图?谢谢你的意见和指导 func addPanReconiser(view: UIView){ let pan = UIPanGestureRecognizer(target: self, action

我有一个函数,它可以创建一条拖拽线,将两个按钮相互连接起来。这很好,但是如果一些按钮相互重叠,如果我在它们重叠的地方拖动,它将同时选择这两个按钮。我只想连接顶部的按钮

我认为问题在于sender.location选择顶部和底部的层。有没有办法告诉sender.location仅选择俯视图?谢谢你的意见和指导

func addPanReconiser(view: UIView){

    let pan = UIPanGestureRecognizer(target: self, action: #selector(DesignViewController.panGestureCalled(_:)))
    view.addGestureRecognizer(pan)
}

@objc func panGestureCalled(_ sender: UIPanGestureRecognizer) {

    let currentPanPoint = sender.location(in: self.view)

    switch sender.state {
    case .began:

        panGestureStartPoint = currentPanPoint
        self.view.layer.addSublayer(lineShape)

    case .changed:
        let linePath = UIBezierPath()
        linePath.move(to: panGestureStartPoint)
        linePath.addLine(to: currentPanPoint)

        lineShape.path = linePath.cgPath
        lineShape.path = CGPath.barbell(from: panGestureStartPoint, to: currentPanPoint, barThickness: 2.0, bellRadius: 6.0)

        for button in buttonArray {
            let point = sender.location(in: button)

            if button.layer.contains(point) {
                button.layer.borderWidth = 4
                button.layer.borderColor = UIColor.blue.cgColor
            } else {
                button.layer.borderWidth = 0
                button.layer.borderColor = UIColor.clear.cgColor
            }
        }

    case .ended:

        for button in buttonArray {
            let point = sender.location(in: button)

            if button.layer.contains(point){

                //DO my Action here
                lineShape.path = nil
                lineShape.removeFromSuperlayer()

            }
        }
    default: break
    }
  }
}
注意:一些代码行来自自定义扩展。我把它们放在里面,因为它们是不言自明的


感谢您的帮助

A
UIView
有一个名为
子视图
的属性,其中索引较高的元素位于索引较低的元素之前。例如,索引为1的子视图位于索引为0的子视图的前面

也就是说,要获得位于顶部的按钮,您应该按照组织
UIView
属性的方式对
buttonArray
进行排序。假设您的按钮都是同一个
UIView
的同级按钮(可能不一定如此,但您可以调整它们以便正确排序):


因此,保持您的
按钮按这种方式排序,您想要的按钮就是包含
let point=sender.location(in:button)
的按钮,该按钮在数组中具有较高的索引。

有一种方法可以四处走动。看起来你只是想让你的手势结束于一个按钮之上,因此在循环外添加一个var,每次选择一个按钮时,将其与z级别的var进行比较

case .ended:
        var pickedButton: UIButton?
        for button in buttonArray {
            let point = sender.location(in: button)

            if button.layer.contains(point){
                if pickedButton == nil {
                    pickedButton = button
                } else {
                    if let parent = button.superView, parent.subviews.firstIndex(of: button) > parent.subviews.firstIndex(of: pickedButton!) {
                        pickedButton = button
                    }
                }
            }
        }
        //DO my Action with pickedButton here
        lineShape.path = nil
        lineShape.removeFromSuperlayer()

谢谢阿杰弗森,我试过了,但没有解决问题。我正在考虑创建一个位置数组,当有多个位置时进行过滤。谢谢Lili!这是可行的,我确实稍微修改了代码,因为“if let parent=button.superView,parent.subviews.firstIndex(of:button)>parent.subviews.firstIndex(of:pickedButton!)”一行不断抛出一个错误,但最终还是成功了
case .ended:
        var pickedButton: UIButton?
        for button in buttonArray {
            let point = sender.location(in: button)

            if button.layer.contains(point){
                if pickedButton == nil {
                    pickedButton = button
                } else {
                    if let parent = button.superView, parent.subviews.firstIndex(of: button) > parent.subviews.firstIndex(of: pickedButton!) {
                        pickedButton = button
                    }
                }
            }
        }
        //DO my Action with pickedButton here
        lineShape.path = nil
        lineShape.removeFromSuperlayer()