更新[11/1/2018]:
我尝试逐步测试代码,发现:
- 方法touchesEnd从未被调用为剩余的UIView。
- 方法相同触摸已取消
我正在遵循有关实施多点触控应用程序的Apple文档。
网址是 : https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_touches_in_your_view/implementing_a_multitouch_app
我正在使用4种方法: - touchesBegan(:with:), - touchesMoved(:with:), - touchesEnded(:with:), - 触摸取消(:与:)
以在调用触摸开始时在触摸位置创建 UIView。在调用 touchesMoving 时更新 UIView 位置。最后,在调用触摸结束和触摸取消时删除 UIView。
问题是当我在屏幕上快速点击时,UIView 不会从超级视图中删除。代码与URL中提供的代码基本相同,但图形不同。我添加了另一个视图,它从触摸位置偏移了一点,以便在触摸点上获得更好的外观。
剩余的 UIView 示例
另一张图片,与下面的评论代码相同
我不明白出了什么问题,为什么会这样。我怀疑 touchesEnded() 从未被调用过,但我不知道为什么。我想问有什么方法可以防止这种情况发生(没有剩余的 UIView)?
我使用的是XCode版本9.2(9C40b)和iPad Air 2。 我在不同的iPad型号上尝试了该应用程序,并发生了同样的事情。
部分代码:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
createViewForTouch(touch: touch)
}
}
func createViewForTouch( touch : UITouch ) {
let newView = TouchSpotView() //TouchSportView is a custom UIView
newView.bounds = CGRect(x: 0, y: 0, width: 1, height: 1)
newView.center = touch.location(in: self)
// Add the view and animate it to a new size.
addSubview(newView)
UIView.animate(withDuration: 0.2) {
newView.bounds.size = CGSize(width: 100, height: 100)
}
// Save the views internally
touchViews[touch] = newView //touchViews is a dict, i.e. touchView[UITouch:TouchSportView]
}
func removeViewForTouch (touch : UITouch ) {
if let view = touchViews[touch] {
view.removeFromSuperview()
touchViews.removeValue(forKey: touch)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
removeViewForTouch(touch: touch)
}
}
有关完整代码,请参阅随附的 URL 以获取 Apple 文档。
非常感谢您的慷慨帮助!!!
尝试了以下代码(从您提供的链接复制粘贴),它在实际设备和模拟器上都能完美运行:
import UIKit
class ViewController: UIViewController {
override func loadView() {
view = TouchableView()
view.backgroundColor = .white
}
}
class TouchableView: UIView {
var touchViews = [UITouch:TouchSpotView]()
override init(frame: CGRect) {
super.init(frame: frame)
isMultipleTouchEnabled = true
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
isMultipleTouchEnabled = true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
createViewForTouch(touch: touch)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let view = viewForTouch(touch: touch)
// Move the view to the new location.
let newLocation = touch.location(in: self)
view?.center = newLocation
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
removeViewForTouch(touch: touch)
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
removeViewForTouch(touch: touch)
}
}
func createViewForTouch( touch : UITouch ) {
let newView = TouchSpotView()
newView.bounds = CGRect(x: 0, y: 0, width: 1, height: 1)
newView.center = touch.location(in: self)
// Add the view and animate it to a new size.
addSubview(newView)
UIView.animate(withDuration: 0.2) {
newView.bounds.size = CGSize(width: 100, height: 100)
}
// Save the views internally
touchViews[touch] = newView
}
func viewForTouch (touch : UITouch) -> TouchSpotView? {
return touchViews[touch]
}
func removeViewForTouch (touch : UITouch ) {
if let view = touchViews[touch] {
view.removeFromSuperview()
touchViews.removeValue(forKey: touch)
}
}
}
class TouchSpotView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.lightGray
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// Update the corner radius when the bounds change.
override var bounds: CGRect {
get { return super.bounds }
set(newBounds) {
super.bounds = newBounds
layer.cornerRadius = newBounds.size.width / 2.0
}
}
}
因此,如果您要使用它做更多操作,请将该附加代码添加到问题中,或者如果您从代码中删除了某些内容,请告诉我们。否则,它应该可以工作。
编辑
为了完整起见,我包含一个指向最小项目的 GitHub 链接,这对我有用。
而不是找到为什么没有调用 touchesCancel 和 touchesEnd,而是使用 event?。allTouches 方法,用于检查未处理 UITouch 的所有触摸。