在我的视图控制器中,我有一个与 UITableView 关联的 UISearchController。所以我所有的普通表视图数据源方法都是旧的
if isSearching {
// use filteredTableData array
} else {
// use SharedModel.shared.participants
}
我不清楚如何使用 RxCocoa 来实现它,因为我是 Rx 的新手。
在我的视图控制器中,我有一个与 UITableView 关联的 UISearchController。所以我所有的普通表视图数据源方法都是旧的
if isSearching {
// use filteredTableData array
} else {
// use SharedModel.shared.participants
}
我不清楚如何使用 RxCocoa 来实现它,因为我是 Rx 的新手。
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
}
我通过为 an 声明一个装饰器Observable
并为 a 声明一个扩展来解决这个问题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 }
}