簡體   English   中英

Swift Combine - 如何獲得為 UITextField 的文本屬性的每個字符更改提供事件的發布者

[英]Swift Combine - How to get a Publisher that delivers events for every character change of UITextField's text property

我注意到

textField.publisher(for: \.text)

在編輯完成時傳遞事件,但不是針對每個字符/編輯更改。 我如何獲得一個發布者,它會為每次更改發送事件? 在 ReactiveSwift 中,它將是

textField.reactive.continousTextValues()

而在 RxSwift 中,它只是( 如何在 RxSwift 中每次 UITextField 文本屬性更改時獲得信號

textField.rx.text

我采取的方法:

  • 檢查publisher(for:options:)方法,但沒有適合預期結果的選項。
  • 添加目標/操作textField.addTarget(self, action: #selector(theTextFieldDidChange), for: .editingChanged)UITextField 文本更改事件
  • 通過接口構建器連接操作,與上一步基本相同,這都會導致額外的工作和混亂的代碼。
  • 觀看 2019 年關於 Combine 的 WWDC 視頻。 他們沒有處理文本字段,而是使用@Published變量,隱藏值實際上來自 - (或者我錯過了什么?)。

我目前不知道如何做到這一點,我覺得有回到 ReactiveSwift 的趨勢,但我想問你,在退步之前。

不幸的是,Apple 沒有為此向 UIKit 添加發布者,並且因為 UIControl 沒有實現 KVO, publisher(for:)發布者並沒有像預期的那樣工作。 如果您能夠接受添加依賴於你的項目有幾個很好的UIControl出版商在這里

或者,您可以實現自己的發布者來執行此操作,或者訂閱文本字段更改舊學校的方式。

在 UITextField 的情況下,您可以使用此擴展名:

  extension UITextField {
    func textPublisher() -> AnyPublisher<String, Never> {
        NotificationCenter.default
            .publisher(for: UITextField.textDidChangeNotification, object: self)
            .map { ($0.object as? UITextField)?.text  ?? "" }
            .eraseToAnyPublisher()
    }
  }

用作:textField.textPublisher()

您始終可以根據需要創建自定義發布者。 例如,在這里我創建了 TextField 發布者,它為 textField 包裝了 textFieldDidChange 操作並在輸入/刪除每個字符后發送 String ! 請復制鏈接,所以不會解析它:

https://github.com/DmitryLupich/Combine-UIKit/blob/master/CombineCustomPublishers/🚜%20Publishers/TextFieldPubisher.swift

如果這是您要查找的內容,我猜UITextField會同時發出通知和控制事件,因此您可以通過收聽通知來實現,例如:

import UIKit
import Combine

class ViewController: UIViewController {

    @IBOutlet private var textField: UITextField!

    var cancellables = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        let textFieldPublisher = NotificationCenter.default
            .publisher(for: UITextField.textDidChangeNotification, object: textField)
            .map( {
                ($0.object as? UITextField)?.text
            })
        
        textFieldPublisher
            .receive(on: RunLoop.main)
            .sink(receiveValue: { [weak self] value in
                print("UITextField.text changed to: \(value)")
            })
            .store(in: &cancellables)
    }
}

讓我知道這是否是您的實際目標。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM