当使用UISearchController时,RxSwift UITableView绑定

时间:2017-11-26 19:24:16

标签: uitableview uisearchcontroller rx-swift rx-cocoa

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

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

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

2 个答案:

答案 0 :(得分:0)

创建一个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
}

答案 1 :(得分:0)

我通过声明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 }

}