Search code examples
uikitswift3uitouchuieventtouchesended

Getting a vector from a touch location in swift 3


As the title says, how can I accomplish this? I can get the first touch but I don't know how to get the last touch if it is a swiping gesture. With the following code I get the error: value of type 'Set' has no member 'last'. Not really sure how to get the position when the touch is released.

override func touchesMoved(_ touches: Set<UITouch>, with: UIEvent?){
    let firstTouch:UITouch = touches.first! as UITouch
    let lastTouch:UITouch = touches.last! as UITouch

    let firstTouchLocation = firstTouch.location(in: self)
    let lastTouchLocation = lastTouch.location(in: self)

}

I want to get the location of the first point and the location of the second point. Then I would like to use the duration of the swipe, the size of the line, and the angle of the line to create an impulse vector to use on an SKNode. Is there any way to extract this information using the UITouch? Any help is greatly appreciated. Thanks for your time!

I also have basic touches on the screen that run functions

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch:UITouch = touches.first! as UITouch
    let touchLocation = touch.location(in: self)
    if playButton.contains(touchLocation) && proceed == true{
        playSound1()
        Ball.physicsBody?.affectedByGravity = true
        proceed = false}
    else if infoButton.contains(touchLocation) && proceed == true{
        playSound1()
        loadScene2()}
    else {}
}

Solution

  • You have to store the values in touches began and compare with the values in touches ended and then do the calculations there. Note that a touch can be canceled by something like a phone call so you need to anticipate that as well.

        class v: UIViewController {
            var startPoint: CGPoint?
            var touchTime = NSDate()
            override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
                guard touches.count == 1 else {
                    return
                }
                if let touch = touches.first {
                    startPoint = touch.location(in: view)
                    touchTime = NSDate()
                }
            }
    
            override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
                defer {
                    startPoint = nil
                }
                guard touches.count == 1, let startPoint = startPoint else {
                    return
                }
                if let touch = touches.first {
                    let endPoint = touch.location(in: view)
                    //Calculate your vector from the delta and what not here
                    let direction = CGVector(dx: endPoint.x - startPoint.x, dy: endPoint.y - startPoint.y)
                    let elapsedTime = touchTime.timeIntervalSinceNow
                    let angle = atan2f(Float(direction.dy), Float(direction.dx))
                }
            }
    
            override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
                startPoint = nil
            }
        }