也使用 UISearchController 时的 RxSwift UITableView 绑定

Posted

技术标签:

【中文标题】也使用 UISearchController 时的 RxSwift UITableView 绑定【英文标题】:RxSwift UITableView binding when also using a UISearchController 【发布时间】:2017-11-26 19:24:15 【问题描述】:

在我的视图控制器中,我有一个与 UITableView 关联的 UISearchController。所以我所有的普通表视图数据源方法都是旧的

if isSearching 
    // use filteredTableData array
 else 
    // use SharedModel.shared.participants 

我不清楚如何使用 RxCocoa 来实现它,因为我是 Rx 的新手。

【问题讨论】:

【参考方案1】:

创建一个Variable,如下所示

var tableViewOptions = Variable<[String]>([]) // replace String with your own object

在视图加载后将tableViewOptions 绑定到tableview

tableViewOptions
  .asObservable()
  .bind(to: self.tableView
    .rx
    .items(cellIdentifier: "cellIdentifier",
           cellType: CustomCell.self))  _, values, cell in
           // do your stuff

然后,当您搜索更改 tableViewOptions 的值时,如下所示。

if isSearching 
  tableViewOptions.value = filteredTableArray
 else 
  tableViewOptions.value = SharedModel.shared.participants

【讨论】:

【参考方案2】:

我通过为Observable 声明一个装饰器和为UISearchBar 声明一个扩展来解决这个问题(您也可以为UISearchController 声明它):

//FIXME: Item can't be type constrained. Have to use optional casting.
class FilterableByTitleCollection<Item>: ObservableType 

    private let origin: Observable<Array<Item>>
    private let filteringStrategySource: Observable<TitlableModelFilteringStrategy> //FIXME: This is a strategy source

    init<Origin: ObservableType>(
        origin: Origin,
        filteringStrategySource: Observable<TitlableModelFilteringStrategy>) where Origin.E == Array<Item> 
        self.origin = origin.asObservable()
        self.filteringStrategySource = filteringStrategySource
    

    typealias E = Array<Item>
    func subscribe<O:ObserverType>(_ observer: O) -> Disposable where O.E == Array<Item> 
        return Observable.combineLatest(
                origin,
                filteringStrategySource
            )
            .observeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
            .map origin, strategy in
                guard origin is Array<Titlable> else  assert(false); return origin 
                return origin.filter strategy.shouldInclude(item: $0 as! Titlable) 
            
            .observeOn(MainScheduler.instance)
            .subscribe(observer)
    


...

extension UISearchBar 

    var titlableFilteringStrategy: Observable<TitlableModelFilteringStrategy> 
        return Observable<String?>.merge(
            [
                self.rx.text.asObservable(),
                self.rx.textDidEndEditing
                    .map [weak self] in
                        assert(self != nil)
                        return self?.text
                    ,
                self.rx.cancelButtonClicked.map Optional<String>.some("") 
            ]
        ).distinctUntilChanged (old: String?, new: String?) -> Bool in
            old == new
        .map TitlableModelFilteringStrategy(filteringPredicate: $0) 
    


...

struct TitlableModelFilteringStrategy 

    private let filteringPredicate: String
    init(filteringPredicate: String?) 
        self.filteringPredicate = filteringPredicate ?? ""
    

    func shouldInclude(item: Titlable) -> Bool 
        return filteringPredicate.isEmpty ? true : item.title.localizedCaseInsensitiveContains(filteringPredicate)
    

    func equals(to another: TitlableModelFilteringStrategy) -> Bool 
        return filteringPredicate == another.filteringPredicate
    


...

protocol Titlable 

    var title: String  get 


【讨论】:

以上是关于也使用 UISearchController 时的 RxSwift UITableView 绑定的主要内容,如果未能解决你的问题,请参考以下文章

模态关闭时的 UISearchController 问题

UISearchController UISearchBar 背景

从 UISearchController 搜索栏快速删除黑色边框

标签栏和 UISearchController 出现黑屏

UISearchController:即使搜索栏为空也显示结果

使用 UISearchController 时如何删除排序/过滤的项目