在Xcode 8.1 / Swift 3.0中使用调试器断点调用两次Delegate方法

我有一个 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()
}

解决方法

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

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

>触摸时,调用backspacepressed
> 0.5秒后,如果触摸仍然按下,请再次调用backspacepressed
>每隔0.1秒后,请再次调用backspacepressed

以下是我将如何实现它:

>将其添加到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,height: 150)
view.addSubview(button)

>在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()
}

>(可选)注释掉您的日志,以便您的控制台与我的实验相匹配

func backspacepressed( ){
    //print("in backspacepressed")
}

没有断点,如果点击并按住此按钮,您将按照上面概述的行为打印日志:

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的键盘正在做类似的事情,并且你设置了一个断点,让你的触摸停滞不前,而某个计时器决定是的,这确实是一个长期的新闻!即使它确实不是.我没有一个解决方法,但希望这会对正在发生的事情有所启发.

相关文章

在有效期内的苹果开发者账号(类型为个人或者公司账号)。还...
Appuploader官网--IOS ipa上传发布工具,证书制作工具跨平台...
苹果在9月13号凌晨(北京时间)发布 iOS 16,该系统的设备可...
计算机图形学--OpenGL递归实现光线追踪
Xcode 14打出来的包在低版本系统运行时会崩溃,报错信息是Li...