RxSwift - 在 UISearchBar 中以编程方式触发搜索

Posted

技术标签:

【中文标题】RxSwift - 在 UISearchBar 中以编程方式触发搜索【英文标题】:RxSwift - trigger search programmatically in UISearchBar 【发布时间】:2017-11-19 22:55:48 【问题描述】:

当用户键入一些文本时,我正在观察 UISearchBar.rx.text 属性以执行一些与搜索相关的操作。 但有时,我也想以编程方式触发此搜索操作。例如,在创建此示例中的视图时,不幸的是没有打印“搜索 [...]”文本。

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController 
  @IBOutlet weak var mySearchBar: UISearchBar!

  let disposeBag = DisposeBag()

  override func viewDidLoad() 
    super.viewDidLoad()
    // Trigger search when text changes
    mySearchBar.rx.text.subscribe(onNext:  (text)
         print("Searching for \(text)...")
         // do some search Action
    
    .disposed(by: disposeBag)

    // Programmatically trigger a search
    mySearchBar.text = "Some text to search"
  


问题是更改 mySearchBar.text 不会触发新的 rx.text 事件。有什么办法吗?

例如,感谢this post,我知道使用 UITextField,可以使用 UITextField.sendActions(for: .ValueChanged) 函数。 UISearchBar 有类似的方法吗?

【问题讨论】:

【参考方案1】:

您可以使用Variable<String?> 作为搜索栏更新的接收器。这样,您还可以通过编程方式设置其值,并直接使用变量而不是搜索栏来驱动您的操作:

class ViewController: UIViewController 
    let searchText = Variable<String?>(nil)
    let searchBar = UISearchBar()
    let disposeBag = DisposeBag()

    override func viewDidLoad() 
        super.viewDidLoad()
        searchBar.rx.text.asDriver()
            .drive(searchText)
            .disposed(by: disposeBag)

        searchText.asObservable().subscribe(onNext:  [weak self] (text) in
            if let welf = self, welf.searchBar.text != text 
                welf.searchBar.text = text
            
        )
            .disposed(by: disposeBag)

        searchText.value = "variables so cool"
        searchText.asObservable().subscribe(onNext:  [weak self] (text) in
            self?.doStuff(text)
        )
        .disposed(by: disposeBag)
    

【讨论】:

没问题。您还应该查看RxExamples 中的&lt;-&gt; 运算符。【参考方案2】:

这是Drivers的简单用法

import UIKit
import RxCocoa
import RxSwift
class SearchViewController: UIViewController 

    @IBOutlet weak var searchBar: UISearchBar!
    let disposeBag = DisposeBag()
    override func viewDidLoad() 
        super.viewDidLoad()
        let dataModels = Driver.just(["David", "Behrad","Tony","Carl","Davidov"])
        let searchingTextDriver = searchBar.rx.text.orEmpty.asDriver()
        let matchedCases = searchingTextDriver.withLatestFrom(dataModels) searchingItem,models in
            return models.filter( (item) -> Bool in
                 return item.contains(searchingItem)
            )
        
        matchedCases.do(onNext:  (items) in
            print(items)            
        ).drive().disposed(by: disposeBag)
    

如您所见,我们创建了一个dataModels 驱动程序,它可能是您的网络或数据库获取的响应。 搜索文本转换为驱动程序,然后与dataModels 混合以创建matchedCases

【讨论】:

【参考方案3】:

是的,UITextBar 也是如此。

以编程方式设置.text不会自动触发动作,我不知道为什么!但UITextField 也是如此。

每次更新 UIView 子类的 .text 属性后调用 sendActions

试试这个:

// Programmatically trigger a search
    mySearchBar.text = "Some text to search"    
    mySearchBar.sendActions(for: .valueChanged)

【讨论】:

这适用于 ios 13 及更高版本中的 UISearchBar,方法是调用 searchTextField.sendActions(for:) 方法

以上是关于RxSwift - 在 UISearchBar 中以编程方式触发搜索的主要内容,如果未能解决你的问题,请参考以下文章

如何在 RxSwift 中取消订阅 Observable?

如何在 UINavigation 中显示 UISearchBar?

RxSwift + UITableViewCell 如何在 heightForRowAt 中获取单元格对象

在 RxSwift 4.0.0 中正确使用 retryWhen 运算符

RxSwift 映射问题

不能在 DelegateProxyType (rxSwift) 中使用 proxyForObject 函数