我从 RxSwift 开始,并尝试获得一个使用 UISearchController 过滤数据源的简单示例。
我已将 UISearchController 连接到 UITableViewController 的基本设置。使用 MVVM 我还有一个基本的 View 模型设置来驱动表格。
self.viewModel.searchText.accept(searchController.searchBar.text ?? "")
viewModel.listItems.bind(to: tableView.rx.items(cellIdentifier: "ItemCell")) { row, item, cell in
cell.textLabel!.text = item.name
}
.disposed(by: disposeBag)
查看模型
class ListViewModel {
private let sourceItems: BehaviorRelay<[ListItem]> = BehaviorRelay(value: [
ListItem(name: "abc"),
ListItem(name: "def"),
ListItem(name: "ghi"),
ListItem(name: "jkl"),
ListItem(name: "mno")
])
let searchText = BehaviorRelay<String>(value: "")
var listItems: Observable<[ListItem]> = Observable.just([])
init() {
listItems = sourceItems.asObservable()
}
}
我可以添加搜索过滤,这样只有匹配过滤字符串的值才会显示
let searchObservable = searchText
.throttle(.milliseconds(300), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.filter { query in
return query.count > 2
}
.share(replay: 1)
listItems = Observable.combineLatest(sourceItems.asObservable(), searchObservable) { items, query in
return items.filter({ item in
item.name.lowercased().contains(query.lowercased())
})
}
但是,在过滤器匹配之前,这不会显示任何值。我想要做的是最初显示所有值,然后只显示过滤后的值。当 searchText
更改但为空或事件被过滤掉时,我不太确定如何填充 listItems
。
最佳答案
你忘了订阅更改,而不是
listItems = Observable.combineLatest(sourceItems.asObservable(), searchObservable) { items, query in
return items.filter({ item in
item.name.lowercased().contains(query.lowercased())
})
}
应该是
Observable.combineLatest(sourceItems.asObservable(), searchObservable) { items, query in
return items.filter({ item in
item.name.lowercased().contains(query.lowercased())
})
}.subscribe(onNext: { resultArray in
print(resultArray) // here you can change your listItems
})
.disposed(by: disposeBag)
这是更改搜索文本的方法 searchText.accept("123")
更新:
要处理任何 searchBar 更新,您应该实现 serachBar.rx 这是一些示例如何
import UIKit
import RxSwift
import RxCocoa
class ListItem: NSObject {
var name: String = ""
public init(name str: String) {
super.init()
name = str
}
}
class ViewController: UIViewController, UISearchBarDelegate {
@IBOutlet weak var searchBar: UISearchBar!
private let sourceItems: BehaviorRelay<[ListItem]> = BehaviorRelay(value: [
ListItem(name: "abc"),
ListItem(name: "def"),
ListItem(name: "ghi"),
ListItem(name: "jkl"),
ListItem(name: "mno")
])
let searchText = BehaviorRelay<String>(value: "")
var listItems: Observable<[ListItem]> = Observable.just([])
var disposeBag: DisposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
addSearchBarObserver()
listItems = sourceItems.asObservable()
Observable.combineLatest(sourceItems.asObservable(), searchText) { items, query in
return items.filter({ item in
item.name.lowercased().contains(query.lowercased())
})
}.subscribe(onNext: { resultArray in
print(resultArray)
})
.disposed(by: disposeBag)
}
private func addSearchBarObserver() {
searchBar
.rx
.text
.orEmpty
.debounce(.milliseconds(300), scheduler: MainScheduler.instance)
.distinctUntilChanged()
.subscribe { [weak self] query in
guard
let query = query.element else { return }
self?.searchText.accept(query)
}
.disposed(by: disposeBag)
}
}
关于swift - 使用 MVVM 使用 RxSwift 查看初始数据源和过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57286750/