swift - 使用 MVVM 使用 RxSwift 查看初始数据源和过滤

标签 swift mvvm rx-swift

我从 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/

相关文章:

ios - ARKit 2 - 裁剪识别图像

iOS - 当 TextView 位于表格 View 单元格中时将其滚动到顶部

c# - 将值 UserControl 传递给 View Page 的 ViewModel

mvvm - react 性扩展(Rx)+ MVVM =?

ios - RxSwift 让 Observable 触发一个主题

swift - 具有泛型类型的可观察扩展

swift - 如何执行推送 UIViewController 或呈现 UIAlertController?

ios - 过滤服务器响应 RestKit + CoreData

ios - iOS 11.2.6 更新后应用程序崩溃

java - Dagger2 看不到在其他模块中定义的带有@Provide 注解的方法。没有 @provides-annotated 方法就无法提供