自定义UIControl,动作被调用两次

3

我正在尝试创建一个UIControl的子类,以便跟踪触摸事件以改变控件外观。

我不知道为什么,但如果我从IB或代码中添加操作(用于.TouchUpInside),当我触摸控件时,注册操作方法会被调用两次。
堆栈跟踪告诉我,第一次调用来自_sendActionsForEvents: withEvent:,第二次则不清楚。
下面是我如何重写跟踪方法的方式:

 override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        let touchPoint = touch.locationInView(self)
        if CGRectContainsPoint(bounds, touchPoint) {
            sendActionsForControlEvents(.TouchDragInside)
        }
        else {
            sendActionsForControlEvents(.TouchDragOutside)
        }
        return true
    }


override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
    sendActionsForControlEvents(.TouchDown)
    return true
}

override func endTrackingWithTouch(touch: UITouch?, withEvent event: UIEvent?) {
    guard let tou = touch else { return }
    let touchPoint = tou.locationInView(self)
    if CGRectContainsPoint(bounds, touchPoint) {
        sendActionsForControlEvents(.TouchUpInside)
    }
    else {
        sendActionsForControlEvents(.TouchUpOutside)
    }
}

override func cancelTrackingWithEvent(event: UIEvent?) {
    sendActionsForControlEvents(.TouchCancel)
}

我还发现了这个答案,但它似乎不适用于我的问题,因为当我为.TouchUpInside事件添加目标时,我不会像该答案中所述那样自动从事件分派器获取任何操作。


你是否在每个sendActionsForControlEvents上设置了断点,看看是否击中了多个?您是否会为touchDown和touchUpInside分别触发一次事件? - fsb
当然,我想我已经找到了答案。稍后我会发布它。基本上,似乎动作已经由超类发送,但我想追踪所有事件还是只有一些。所以我正在发送已经发送的东西。 - Andrea
1个回答

4

我发现自己误解了文档,很可能还有很多人也误解了(因为在互联网上看到了一些样例)。
重写所提及的方法并不能让你能够管理事件分发,要做到这一点,最好使用 sendAction:to:forEvent:
这些考虑是在我用 UIControl 的子类创建了一个小项目,并为最受欢迎的控件事件添加了一些操作之后得出的:

  • 按下触摸
  • 内部触摸抬起
  • 外部触摸抬起
  • 拖动到外部
  • 拖动到内部
  • 值已更改

结果
除了值已更改以外,所有其他事件都已被调用,即使跟踪方法被覆盖。如果我们想发送值更改,必须自己调用它,这是有意义的,因为根据其名称,它与触摸无关。
我发现有趣的一件事是,当调用跟踪到外部时,当用户将手指拖到控件边界的外面约50%时,它似乎会被调用,而我原以为会在穿过边界后立即调用该方法。

class TestControl: UIControl {
    override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        let touchPoint = touch.locationInView(self)
        print(touchPoint)
        return true
    }
    override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        let touchPoint = touch.locationInView(self)
        print(touchPoint)

        return true
    }

    override func endTrackingWithTouch(touch: UITouch?, withEvent event: UIEvent?) {
        guard let touch = touch else { return }
        let touchPoint = touch.locationInView(self)
        print(touchPoint)

    }
}

class ViewController: UIViewController {

    @IBOutlet weak var tezst: TestControl!


    @IBAction func touchDown(sender: AnyObject){
        print("Touch Down")
    }
    @IBAction func touchUpInside(sender: AnyObject){
        print("Touch up inside")
    }

    @IBAction func touchUpOutside(sender: AnyObject){
        print("Touch up outside")
    }
    @IBAction func touchDragOutside(sender: AnyObject){
        print("Touch drag outside")
    }
    @IBAction func touchDragInside(sender: AnyObject){
        print("Touch drag inside")
    }
    @IBAction func valueChanged(sender: AnyObject){
        print("Value changed")
    }
}

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