7

So I've been messing around trying to get the coordinates of touches on the screen. So far I can get the coordinates of one touch with this:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    let touch = touches.anyObject()! as UITouch
    let location = touch.locationInView(self.view)
    println(location)
}

But when touching with two fingers I only get the coordinates of the first touch. Multi-touch works (I tested with this little tutorial: http://www.techotopia.com/index.php/An_Example_Swift_iOS_8_Touch,_Multitouch_and_Tap_Application). So my question is, how do I get the coordinates of the second (and third, fourth...) touch?

Fr4nc3sc0NL
  • 555
  • 1
  • 6
  • 22

6 Answers6

15

** Updated to Swift 4 and Xcode 9 (8 Oct 2017) **

First of all, remember to enable multi-touch events by setting

self.view.isMultipleTouchEnabled = true

in your UIViewController's code, or using the appropriate storyboard option in Xcode:

xcode screenshot

Otherwise you'll always get a single touch in touchesBegan (see documentation here).

Then, inside touchesBegan, iterate over the set of touches to get their coordinates:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let location = touch.location(in: self.view)
        print(location)
    }
}
Para
  • 3,681
  • 4
  • 23
  • 34
  • Thank you for your answer! I marked giorashc's answer as most helpful because he gave slightly more information, but both methods work :) – Fr4nc3sc0NL Feb 24 '15 at 14:03
  • You're welcome! It's your call, of course :) I've edited the answer a little bit and left references to the documentation, underlining how it's important to enable multi-touch or the code won't work (we always forget about that!). I'm leaving this answer as a reference for other people who might need that detail :) – Para Feb 24 '15 at 14:37
4

the given touches argument is a set of detected touches. You only see one touch because you select one of the touches with :

touches.anyObject() // Selects a random object (touch) from the set

In order to get all touches iterate the given set

for obj in touches.allObjects {
   let touch = obj as UITouch
   let location = touch.locationInView(self.view)
   println(location)
}
giorashc
  • 13,691
  • 3
  • 35
  • 71
1

You have to iterate over the different touches. That way you can access every touch.

for touch in touches{
  //Handle touch
  let touchLocation = touch.locationInView(self.view)
}
Christian
  • 22,585
  • 9
  • 80
  • 106
1

In Swift 1.2 this has changed, and touchesBegan now provides a Set of NSObjects. To iterate through them, cast the touches collection as a Set of UITouch objects as follows:

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

    var touchSet = touches as! Set<UITouch>

    for touch in touchSet{
        let location = touch.locationInView(self.view)
        println(location)
    }
}
Andrew
  • 690
  • 7
  • 11
  • Should I mark this answer as answer to the question? (Since the now marked answer isn't really an answer anymore) – Fr4nc3sc0NL Sep 18 '15 at 08:26
0

For Swift 3, based on @Andrew's answer :

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    let touchSet = touches

    for touch in touchSet{
        let location = touch.location(in: self.view)
        print(location)
    }
}

EDIT, My bad, that's not answering your question, had the same problem and someone linked me to this previous answer :

Anyway, I had to change few things to make it works in swift 3, here is my current code :

var fingers = [String?](repeating: nil, count:5)

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    for touch in touches{
        let point = touch.location(in: self.view)
        for (index,finger)  in fingers.enumerated() {
            if finger == nil {
                fingers[index] = String(format: "%p", touch)
                print("finger \(index+1): x=\(point.x) , y=\(point.y)")
                break
            }
        }
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesMoved(touches, with: event)
    for touch in touches {
        let point = touch.location(in: self.view)
        for (index,finger) in fingers.enumerated() {
            if let finger = finger, finger == String(format: "%p", touch) {
                print("finger \(index+1): x=\(point.x) , y=\(point.y)")
                break
            }
        }
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
    for touch in touches {
        for (index,finger) in fingers.enumerated() {
            if let finger = finger, finger == String(format: "%p", touch) {
                fingers[index] = nil
                break
            }
        }
    }
}

I still have a little problem but I think it's linked to my GestureRecognizer in my code. But that should do the trick. It will print you the coordinate of each point in your consol.

Hawkydoky
  • 194
  • 1
  • 15
0

In Swift 3,4 Identify touch pointer by its hash:

// SmallDraw
func pointerHashFromTouch(_ touch:UITouch) -> Int {
    return Unmanaged.passUnretained(touch).toOpaque().hashValue
}