如何追踪多点触控

4

嘿,我有一段很好的代码,在我的touches moved方法里,是由@Sam_M给我的。

我正在尝试追踪多个手指的位置,例如手指1在这里,手指2在那里。所以,现在它将打印当前视图上触摸/手指的数量和位置,但它不会分别跟踪每个手指的位置。我已经查看了stackoverflow上其他三个问题,但没有一个能给我一个可以在Swift中实现的好结果。

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

for touch: UITouch in event!.allTouches()! {

for (index,touch) in touches.enumerate() {
    let ptTouch = touch.locationInNode(self.view)
    print("Finger \(index+1): x=\(pTouch.x) , y=\(pTouch.y)")
 }
}

}

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

for touch: UITouch in event!.allTouches()! {

for (index,touch) in touches.enumerate() {
    let ptTouch = touch.locationInNode(self.view)
    print("Finger \(index+1): x=\(pTouch.x) , y=\(pTouch.y)")
  }
 }
}
2个回答

8

当手指在屏幕上时,每个手指的触摸对象在内存中的地址都保持不变。你可以通过将触摸对象的地址存储在数组中,并与该数组进行比较,以跟踪多点触控场景中的每根手指并确定其运动。

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

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    super.touchesBegan(touches, withEvent: event)
    for touch in touches{
        let point = touch.locationInView(self.view)
        for (index,finger)  in fingers.enumerate() {
            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>, withEvent event: UIEvent?) {
    super.touchesMoved(touches, withEvent: event)
    for touch in touches {
        let point = touch.locationInView(self.view)
        for (index,finger) in fingers.enumerate() {
            if let finger = finger where finger == String(format: "%p", touch) {
                print("finger \(index+1): x=\(point.x) , y=\(point.y)")
                break
            }
        }
    }
}

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

override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
    super.touchesCancelled(touches, withEvent: event)
    guard let touches = touches else {
        return
    }
    touchesEnded(touches, withEvent: event)
}

更新至Swift 4

感谢@Klowne

的贡献。

var fingers = [UITouch?](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] = 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 == 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 == touch {
                fingers[index] = nil
                break
            }
        }
    }
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesCancelled(touches, with: event)
    guard let touches = touches else {
        return
    }
    touchesEnded(touches, with: event)
}

根据苹果的更新文档,现在可以在多点触控序列期间保留触摸,只要它们在序列结束时释放即可。

2
文档中得知:在处理事件时,永远不要保留触摸对象。如果您需要在一个触摸阶段中保留有关触摸的信息,请从该触摸复制该信息。 - matt
嗨,Sam,你能否将这行代码添加到马特的答案中更新一下?@Sam_M - Hunter
@matt 感谢您的评论。我更新了我的答案,使用内存地址代替了之前的方法。 - Swifty
@Hunter 更新了答案。 - Swifty
1
这太荒谬了。文档只是说,如果你记录了一个触摸事件,那么在触摸结束时必须释放它。你可以并且应该保留任何可能需要的对象,只要采取适当措施以避免内存泄漏。 - Luis Vieira Damiani
显示剩余7条评论

3
一个触摸是一个手指。 一个手指就是一个触摸。 通过识别触摸,您可以确定手指;只要该手指触摸屏幕,与特定手指对应的触摸将是完全相同的 相同对象。 要获取特定UITouch的唯一标识符,请获取其内存地址,如下所示:
let uuid = String(format: "%p", theTouch)

您可以将每个触摸的唯一标识符存储在属性中。但是,不要存储触摸本身;苹果公司禁止这样做。


1
"Apple" 没有禁止任何事情。你对这件事有点神秘的态度。文档只是说要释放你存储的任何东西,因为每次触摸开始时都会创建新对象,以防止内存泄漏。 - Luis Vieira Damiani
5
在多点触控过程中,触摸对象会一直存在。在处理多点触控过程时,您可以存储对触摸的引用,只要在序列结束时释放该引用即可。如果您需要在多点触控序列之外存储有关触摸的信息,请从触摸中复制该信息。 - Luis Vieira Damiani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接