UITapGestureRecognizer - Игнорировать нажатие на верхний объект и передавать его объекту под ним - PullRequest
0 голосов
/ 21 января 2020

У меня есть красный SCNNode, который на полпути парит над синим SCNNode. Мне нужно dragEvent для них обоих, поэтому, когда они проведены, они двигаются (что работает нормально). Дело в том, что мне нужен только tapEvent для синего узла.

Я пытался следовать этому ответу от до return nil, если красный узел повернут, чтобы он мог перейти к синий узел. Невозможно вернуть ноль, потому что нет возвращаемого значения: Unexpected non-void return value in void function.

if hitResult.node.name == "Red" {

    return nil // Unexpected non-void return value in void function
}

if hitResult.node.name == "Blue" {
    // do something
}

Как я могу игнорировать событие касания, когда красный узел коснулся, и продолжить событие касания до синий узел под ним?

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

func nodeWasTapped(_ recognizer: UITapGestureRecognizer) {

    guard let sceneView = recognizer.view as? ARSCNView else { return }

    let touchLocation: CGPoint = recognizer.location(in: sceneView)

    let hitResults = sceneView.hitTest(touchLocation, options: [:])

    if !hitResults.isEmpty {

        guard let hitResult = hitResults.first else { return }

        if hitResult.node.name == "Red" {

            // *** ignore this tap and continue to the blue node ***
        }

        if hitResult.node.name == "Blue" {
            // do something
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 21 января 2020

Если вы не хотите, чтобы красный узел получал какие-либо касания, просто удалите оба оператора if, потому что независимо от того, где пользователь нажимает на красный и синий узлы, ваша цель - выполнить один и тот же код:

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

func nodeWasTapped(_ recognizer: UITapGestureRecognizer) {

    guard let sceneView = recognizer.view as? ARSCNView else { return }

    let touchLocation: CGPoint = recognizer.location(in: sceneView)

    let hitResults = sceneView.hitTest(touchLocation, options: [:])

    if !hitResults.isEmpty {

        guard let hitResult = hitResults.first else { return }

        //Do something here, no need for if statements
    }
}
0 голосов
/ 21 января 2020

Я использовал switch statement и fallthrough, которые работали, но есть предостережение. В моем вопросе у меня есть только красный узел и синий узел. После того, как красный узел коснулся, он падает до синего оператора, но если у меня есть другие узлы (что я делаю), это не работает.

Поскольку я не добавил другие узлы в вопрос, это простой обходной путь.

func nodeWasTapped(_ recognizer: UITapGestureRecognizer) {

    guard let sceneView = recognizer.view as? ARSCNView else { return }

    let touchLocation: CGPoint = recognizer.location(in: sceneView)

    let hitResults = sceneView.hitTest(touchLocation, options: [:])

    if !hitResults.isEmpty {

        guard let hitResult = hitResults.first else { return }

        switch hitResult.node.name {

            case "Red":
                fallthrough

            default:
                // do whatever for the blue node
            }
    }
}
0 голосов
/ 21 января 2020

Используйте приведенный ниже метод делегата gestRecognizer для этого

добавьте делегата в ваш распознаватель

//when creating tapreconizer assign delegate too or may be are doing it already
yourTapRecognizer.delegate = self


func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    if touch.view?.isDescendant(of: yourSubView) ?? false {
        return false
    }
    return true
}
...