在Xcode 8.1 / Swift 3.0中使用调试器断点

时间:2016-11-17 18:31:52

标签: xcode delegates swift3 method-overriding

我遇到了xcode 8.1 / swift 3的问题。我认为它可能是调试器XCode软件中的一个错误,但我想如果有人看到我遗漏的东西,我会看到它。我正在开发一个ios应用程序,我需要覆盖与UITextField一起使用的退格方法。我设置了一个委托来监视按下的退格键。该程序一直有效,直到我在重写方法中设置调试器断点(参见下面的代码)。当我这样做时,每次按键而不是一次时,会调用两次退格方法。如果我删除断点代码工作。这只是一个错误还是我做错了什么?这是代码感谢您的帮助!

import UIKit

class ViewController: UIViewController, EqFieldDelegate {

override func viewDidLoad() {
    super.viewDidLoad()

    let newField = EqField()
    newField.myDelegate = self
    newField.becomeFirstResponder()
    view.addSubview(newField)
    newField.frame = CGRect(x: 50, y: 50, width: 200, height: 150)

}

func backspacePressed( ){

    print("in backspacePressed") // breakpoint added here
}

}   

这是UITextField的子类:

import UIKit

class EqField: UITextField {

    var myDelegate: EqFieldDelegate?

    override func deleteBackward() {
        super.deleteBackward()
        myDelegate?.backspacePressed()
    }
}

protocol EqFieldDelegate {
    func backspacePressed()
}

1 个答案:

答案 0 :(得分:1)

我有一个关于为什么会这样的理论。

为了说明,想象一下我们正在制作自己的后退按钮。它应具有以下行为来模仿Apple的:

  1. 触地时,请致电backspacePressed
  2. 0.5秒后,如果触控仍然按下,请再次拨打backspacePressed
  3. 每隔0.1秒后,如果触控仍然按下,请再次拨打backspacePressed
  4. 以下是我将如何实现它:

    1. 将此添加到viewDidLoad

      的末尾
      let button = UIButton(type: .system)
      button.setTitle("Tap Me", for: .normal)
      button.addTarget(self, action: #selector(ViewController.handleButtonTouched(button:)), for: .touchDown)
      button.addTarget(self, action: #selector(ViewController.handleButtonReleased(button:)), for: .touchUpInside)
      button.frame = CGRect(x: 50, y: newField.frame.maxY, width: 200, height: 150)
      view.addSubview(button)
      
    2. viewDidLoad

      之后添加此内容
      var buttonTimer: Timer?
      
      func handleButtonTouched(button: UIButton) {
          buttonTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { [weak self] timer in
      
              print("button's been held down for a while!")
              self?.backspacePressed()
      
              self?.buttonTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { (timer) in
                  print("button's still held down")
                  self?.backspacePressed()
              })
      
          })
          print("button was pressed") // add a breakpoint here
          self.backspacePressed()
      }
      
      
      func handleButtonReleased(button: UIButton) {
          buttonTimer?.invalidate()
      }
      
    3. (可选)注释掉您的日志,以便您的控制台与我的实验室匹配

      func backspacePressed( ){
          //print("in backspacePressed")
      } 
      
    4. 如果没有断点,如果点击并按住此按钮,您将按照上述行为打印日志:

      button was pressed
      button's been held down for a while!
      button's still held down
      button's still held down
      button's still held down
      button's still held down
      

      如果你只是点击按钮(不要按住它),你就会得到

      button was pressed
      

      但是,如果您设置了断点,请点击按钮,在断点点击之后等待一秒钟,再按“继续”,您将获得两个日志:

      button was pressed
      button's been held down for a while!
      

      你会想,既然你没有按住按钮足够长的时间,你就不会得到第二个日志。发生的事情是,即使您在断点处停止,计时器也会下降,并且当执行返回到程序时,计时器的结果将在评估按钮释放之前进行评估。

      我不确定为什么事情按此顺序发生 - 为什么在定时器事件之前不能处理按钮释放?但是你可以看到在正常执行时没有断点,甚至不是先发生什么事情的问题 - 短按钮点击将导致在定时器关闭之前调用handleButtonReleased

      我怀疑在你的情况下,Apple的键盘正在做类似的事情,并且你设置了一个断点让你的触摸停滞不前,而某个计时器决定是的,这确实是一个长期的新闻!即使它确实不是。我没有解决方法,但希望这能让我们了解正在发生的事情。