swift How-to:UITextField等待直到用户停止键入

myzjeezk  于 2023-05-27  发布在  Swift
关注(0)|答案(1)|浏览(104)

我在想最好的办法来处理这件事我目前正在寻找等待,直到用户停止输入(让我们说延迟3秒)之前,运行一些代码。最初我打算使用textFieldDidEndEditing,但正如我们所知,它只在用户返回时执行,而不是在他们停止输入时执行。
目前我使用@IBAction textFieldEditingChanged,但这将执行每个输入字符/数字的代码。我尝试使用像shouldExecuteCode: Bool这样的变量,但由于我解析的是XML,响应几乎是立即的,代码仍然会执行几次。
我在考虑使用某种OperationQueue,只有一个操作或没有并发。
有人有好主意吗?

当前实施情况

@IBAction func textFieldEditingChanged(_ sender: CurrencyTextField) {
        self.viewModel.currentTextFieldIdentifier = sender.textFieldIdentifier
        DispatchQueue.main.asyncAfter(deadline: .now() + viewModel.calculationDelay) {
            if let text = sender.text,
               let value = String.format(text) {
                switch self.viewModel.currentTextFieldIdentifier {
                case .fromCurrency:
                    self.calculateExchange(value: value,
                                           valueCurrency: self.fromCurrencyTextField.currency,
                                           outputCurrency: self.toCurrencyTextField.currency)
                case .toCurrency:
                    self.calculateExchange(value: value,
                                           valueCurrency: self.toCurrencyTextField.currency,
                                           outputCurrency: self.fromCurrencyTextField.currency)
                }
            }
        }
    }

可能实施

NotificationCenter.default
            .publisher(for: UITextField.textDidChangeNotification, object: sender)
            .map({ ($0.object as? UITextField)?.text ?? "" })
            .debounce(for: .milliseconds(500), scheduler: RunLoop.main)
            .sink { [weak self] text in
                guard let self = self  else { return }
                if let value = String.format(text) {
                    print(value)
                    switch self.viewModel.currencyTextFieldIdentifier {
                    case .fromCurrency:
                        self.calculateExchange(value: value,
                                               valueCurrency: self.fromCurrencyTextField.currency,
                                               outputCurrency: self.toCurrencyTextField.currency)
                    case .toCurrency:
                        self.calculateExchange(value: value,
                                               valueCurrency: self.toCurrencyTextField.currency,
                                               outputCurrency: self.fromCurrencyTextField.currency)
                    }
                }
            }
            .store(in: &subscriptions)
kulphzqa

kulphzqa1#

下面是一个使用合并框架的示例。这将设置两个简单的UITextField,并为这两个字段设置一个接收器,以便在3秒内任何文本字段都没有发生更改之前,您不会收到任何通知。

class ViewController: UIViewController {
    var sub: AnyCancellable!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tf1 = UITextField(frame: CGRect(x: 70, y: 70, width: 150, height: 44))
        tf1.borderStyle = .roundedRect
        self.view.addSubview(tf1)

        let tf2 = UITextField(frame: CGRect(x: 70, y: 120, width: 150, height: 44))
        tf2.borderStyle = .roundedRect
        self.view.addSubview(tf2)

        sub = NotificationCenter.default
            .publisher(for: UITextField.textDidChangeNotification, object: nil)
            .debounce(for: .seconds(3), scheduler: RunLoop.main)
            .sink { _ in
                print("\(Date()): tf1: \(tf1.text!), tf2: \(tf2.text!)")
            }
    }
}

您可以在文本字段中键入所有您想要的内容,然后切换到另一个字段并键入。sink块将不会运行,直到您停止在两个文本字段中键入3秒。

相关问题