【问题标题】:UIView created by touchesBegin() doesn't removed because touchesEnded() never get called when user removed the finger from the iPad由 touchesBegin() 创建的 UIView 不会被移除,因为当用户从 iPad 上移除手指时,touchesEnded() 永远不会被调用
【发布时间】:2018-06-19 10:19:53
【问题描述】:

更新[2018 年 11 月 1 日]:

我尝试一步步测试代码,发现:

  • 从未为剩余的 UIView 调用方法 touchesEnded
  • touchesCancelled 方法也是如此

我正在关注有关实现多点触控应用的 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:), - touchesCancelled(:with:)

在调用 touchesBegan 时在触摸位置创建 UIView。调用 touchesMoved 时更新 UIView 位置。最后,在调用 touchesEnded 和 touchCancelled 时移除 UIView。

问题是当我在屏幕上快速点击时,UIView 不会从超级视图中删除。代码与网址中提供的代码基本相同,不同的图形。我添加了另一个视图,它从触摸位置偏移了一点,以便更好地查看触摸点。

Example of the leftover UIView

Another Image, same code as the comment below

我不明白出了什么问题以及为什么会发生这种情况。我怀疑 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)
    }
}

完整代码请查看附件中的苹果文档网址。

非常感谢您的慷慨帮助!!!!

【问题讨论】:

  • 您可以使用您的代码吗? UIView。
  • 很可能,您需要创建一个以 touchesBegan 开头的动画。
  • 代码和苹果文档里的一样
  • 是的,我删除了动画代码,让我试试如果我重新添加动画会发生什么。
  • 完全没有帮助

标签: ios swift ipad uiview uitouch


【解决方案1】:

尝试了以下代码(从您提供的link 复制粘贴),它在实际设备和模拟器上都能完美运行:

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 link 包含在一个适合我的最小项目中。

【讨论】:

  • 我构建了另一个 Xcode 项目并将代码复制并粘贴到视图控制器中。当我非常快速地移动手指时,也会发生同样的事情。我还在原始帖子中附加了另一张图片。
【解决方案2】:

使用 event?.allTouches 方法检查所有未处理 UITouch 的触摸,而不是查找未调用 touchesCancelled 和 touchesEnded 的原因。

【讨论】:

    猜你喜欢
    • 2012-10-27
    • 2013-10-12
    • 2012-03-27
    • 2013-08-29
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 2015-10-15
    相关资源
    最近更新 更多