swift - UITextField + 计时器问题 - 检查 "Editing Changed"但只有一次启动计时器?

标签 swift function delegates uikit textfield

完全披露: 我对所有与 swift/UIKit 相关的东西都非常陌生,所以我希望你能原谅我的无知。


因此,我尝试执行的基本操作是让计时器在任何字符输入 UITextField 时立即开始倒计时 (不会仅通过聚焦触发)

除了每次在文本字段中输入字符时,计时器递归地启动它的 timeInterval 以外,一切看起来和功能都达到了我预期的 90%。

输入 7 个以上的字符后,不到几秒钟,我的 60 秒计时器就远远超过了 0。

使用 editingDidBegin“修复”了这个问题,但是,在这个参数中,当文本字段被点击并获得焦点时计时器开始计时,这对于我想要做的事情来说并不理想。

我的 ViewController 代码:

import UIKit

class SecondViewController: UIViewController, UITextFieldDelegate {
    var textField: UITextField?
    @IBOutlet weak var countDownLabel: UILabel!   
    var seconds = 60
    var timer = Timer()
    @IBAction func inputTextBar(_ sender: Any) {
        func inputTextBar() {
            self.becomeFirstResponder()
        }
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(SecondViewController.counterb), userInfo: nil, repeats: true)
    }
    @objc func counterb() {
        seconds -= 1
        countDownLabel.text = String(seconds)
        if seconds == 0 {
            timer.invalidate()
            countDownLabel.text = "Time's Up!"
        }
    }
    var count = 10
    override func viewDidLoad() {
        super.viewDidLoad()
        textField?.delegate = self
        textField?.becomeFirstResponder()
    }
}

其他值得注意的混淆:如果只键入一个字符,计时器将照常进行并在 0 秒时打印“Times Up!”。并停止。

但如果它在我提到的速度堆积上,在输入几个字符后,计时器会飞过 0 并且永远不会失效。

我认为这是一个刷新问题。

编辑:

好吧,我想通了使计时器变量weak 我能够让计时器不再自行堆叠。但是,对于 weak 变量,在输入 UITextField 时计时器根本不运行!

半固定代码:

weak var timer: Timer?
@IBAction func inputTextBar(_ sender: AnyObject) {
    timer?.invalidate()      
    timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(SecondViewController.loop), userInfo: nil, repeats: true)
}    
@objc func loop() {
    seconds -= 1
    countDownLabel.text = String(seconds)   
    if self.seconds == 0 {
        timer?.invalidate()
        countDownLabel.text = "Time's Up!"
    }   
}

最佳答案

首先将您的计时器声明更改为可选。然后你可以简单地检查它是否为零,如果为真则安排你的计时器。其次,您永远不应该依赖计时器来测量耗时。只需创建一个结束日期,添加从现在开始所需的时间间隔。这样您就可以在使计时器无效时简单地检查 now 是否大于或等于 endDate 。仅使用计时器来更新 UI,您可以在更新标签时简单地检查从现在开始的时间间隔。下面的代码是在浏览器中编写的,因此可能有一些错误,但您可以知道如何实现您的目标。

class SecondViewController: UIViewController {
    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var countDownLabel: UILabel!
    var endDate: Date? = nil
    var timer: Timer? = nil
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
        textField.becomeFirstResponder()
    }
    @objc func editingChanged(_ textField: UITextField) {
        if timer == nil {
            timer = .scheduledTimer(timeInterval: 1,
                                    target: self,
                                    selector: #selector(counterb),
                                    userInfo: nil,
                                    repeats: true)
            endDate = Date().addingTimeInterval(60)
        }
    }
    @objc func counterb() {
        countDownLabel.text = String(format: "%.0f", endDate!.timeIntervalSinceNow.rounded(.up))
        if Date() >= endDate! {
            timer?.invalidate()
            timer = nil
            endDate = nil
            countDownLabel.text = "Time's Up!"
        }
    }
}

关于swift - UITextField + 计时器问题 - 检查 "Editing Changed"但只有一次启动计时器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64516932/

相关文章:

swift - 图像未通过 POST 完整传输到服务器

python - "TypeError: ' int ' object is not iterable"当在函数内部移动 itertools 产品时

php - 在特定时间后在 php 中终止函数?

ios - 在不导入头文件的情况下检查和调用委托(delegate)类的方法

arrays - Swift Array 实例方法 drop(at : Int)

xcode - 是否可以将 GMSPolygon 与 MKMapView 一起使用?

swift - Google 的附近消息 : not receiving any messages

Python-np.random.choice

c# - (Action<T>).Name 不返回预期值

cocoa - 未调用委托(delegate)