如何在SearchBar中使用RxDataSource?

时间:2019-09-08 08:31:17

标签: swift rx-swift

我精通RxSwift,使用RxDataSource时,SearchBar委托对我不起作用,他, 我看不到错误。没有RxDataSource,一切都会正常,在其他屏幕上我也不会出现问题。 换个角度告诉我,这是什么错误?为什么不进行过滤?

private var defaultCategories: [Groups]!
var groupsCoreData = BehaviorRelay<[Groups]>(value: [])

override func viewDidLoad() {
    super.viewDidLoad()
    searchBarRx()
    tableViewRx()
}

let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Groups>>(
    configureCell: { (_, tv, indexPath, element) in
        let cell = tv.dequeueReusableCell(withIdentifier: "addNewWordsToGroup")!
        cell.textLabel?.text = element.title
        return cell
},
    titleForHeaderInSection: { dataSource, sectionIndex in
        return dataSource[sectionIndex].model
}
)

 private func tableViewRx() {
    let dataSource = self.dataSource

    let items = [
        SectionModel(model: "Пример", items: self.defaultCategories
            .filter { $0.titleCategories == "Тест1"}),
        SectionModel(model: "Пример2", items: self.defaultCategories
            .filter { $0.titleCategories == "Тест2" })
        ]

    Observable.just(items)
        .bind(to: tableView.rx.items(dataSource: dataSource))
        .disposed(by: disposeBag)

    tableView
        .rx
        .modelSelected(Groups.self)
        .subscribe(onNext: { [weak self] data in
         }
        .disposed(by: disposeBag)
}

private func searchBarRx() {
    searchBar
        .rx
        .text
        .orEmpty
        .debounce(.microseconds(200), scheduler: MainScheduler.instance)
        .distinctUntilChanged()
        .subscribe { [unowned self] query in
            self.searchBar.showsCancelButton = query.element!.isEmpty
            self.defaultCategories = query.element!.isEmpty ? 
            self.defaultCategories : 
            self.defaultCategories
            .filter({ $0.title?.range(of: query.element!, options: .anchored) != nil
            })
        }
        .disposed(by: disposeBag)
}

query-显示输入字符,但不显示结果。 附言数组不为空

1 个答案:

答案 0 :(得分:2)

关键是您不要替换数据源。 Rx是功能范例,因此不需要替换。相反,您必须先概述不变量。像这样:


final class ViewController: UIViewController {

    var tableView: UITableView!
    var searchBar: UISearchBar!
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        let initialItems = [
            SectionModel(model: "Пример", items: [Groups(title: "Group1", titleCategories: "Тест1")]),
            SectionModel(model: "Пример2", items: [Groups(title: "Group2", titleCategories: "Тест2")])
        ]

        let searchTerm = searchBar.rx.text.orEmpty
            .debounce(.microseconds(200), scheduler: MainScheduler.instance)
            .distinctUntilChanged()

        Observable.combineLatest(Observable.just(initialItems), searchTerm)
            .map { filteredSectionModels(sectionModels: $0.0, filter: $0.1) }
            .bind(to: tableView.rx.items(dataSource: dataSource))
            .disposed(by: disposeBag)
    }
}

func filteredSectionModels(sectionModels: [SectionModel<String, Groups>], filter: String) -> [SectionModel<String, Groups>] {
    guard !filter.isEmpty else { return sectionModels }
    return sectionModels.map {
        SectionModel(model: $0.model, items: $0.items.filter { $0.title?.range(of: filter, options: .anchored) != nil
        })
    }
}

private let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Groups>>(
    configureCell: { (_, tv, indexPath, element) in
        let cell = tv.dequeueReusableCell(withIdentifier: "addNewWordsToGroup")!
        cell.textLabel?.text = element.title
        return cell
    },
    titleForHeaderInSection: { dataSource, sectionIndex in
        return dataSource[sectionIndex].model
    }
)

特别注意如何将包含所有项目的Observable与跟踪当前搜索过滤器的Observable相结合。然后,我只将实际上应该显示的项目发送到表视图。