ios – 用于搜索屏幕的MVVM和RxSwift

为了教育MVVM和Rx
Swift我想构建简单的搜索屏幕,它将有一个表格视图和一个搜索栏.当用户在搜索栏中输入内容时,我将在此表中显示他所拥有的内容.听起来很简单,但我找不到任何适合我的教程.

我已经在视图控制器中编写了所有代码,我只是无法理解必须观察搜索文本的变化然后调用数据库方法,这将通过搜索文本过滤项目.

一些代码,我已经有了.

我的ViewController

import Foundation
import UIKit
import RxSwift
import RxCocoa

class PlaceSearchViewController: UIViewController {

    //MARK: - 

    @IBOutlet weak var searchBar: UISearchBar!
    @IBOutlet weak var tableView: UITableView!

    //MARK: - Dependencies

    private var viewModel: PlaceSearchViewModel!
    private let disposeBag = DisposeBag()

    //MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        viewModel = PlaceSearchViewModel()
        addBindsToViewModel(viewModel)
    }

    //MARK: - Rx

    private func addBindsToViewModel(viewModel: PlaceSearchViewModel) {

        searchBar.rx_text.bindTo(viewModel.searchTextObservable)

        viewModel.placesObservable.bindTo(tableView.rx_itemsWithCellFactory) {
            (tableView: UITableView, index, place: Place) in

            let indexPath = NSIndexPath(forItem: index, inSection: 0)
            let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as PlaceCell

            cell.configureWithObject(place)

            return cell

            }
            .addDisposableTo(disposeBag)

        tableView.rx_contentOffset
            .subscribe { _ in
                if self.searchBar.isFirstResponder() {
                    _ = self.searchBar.resignFirstResponder()
                }
            }
            .addDisposableTo(disposeBag)
    }
}

我的观点模型:

import Foundation
import RxSwift
import RxCocoa

class PlaceSearchViewModel {

    //MARK: - Dependecies
    private let disposeBag = DisposeBag()

    //MARK: - Model

    private let placesObservable: Observable<[Place]>
    var searchTextObservable = Variable<String>("")

    //MARK: - Set up

    init() {

        placesObservable = searchTextObservable.asObservable()
            //wait 0.3 s after the last value to fire a new value
            .debounce(0.3, scheduler: MainScheduler.instance)
            //only fire if the value is different than the last one
            .distinctUntilChanged()
            //convert Observable<String> to Observable<[Place]>
            .flatMapLatest { searchString -> Observable<[Place]> in

                // some code here which I can't write.

            }
            //make sure all subscribers use the same exact subscription
            .shareReplay(1)
    }

}

另外,我有方法[DataBase searchPlaces:searchText]返回地方数组 – [Place].我无法理解在我的ViewModel的flatMapLatest中放置它的位置和方式.

最佳答案 我通过创建Observable< [Place]>为我的DataBase创建反应性包装器.

这是我的代码

placesObservable = searchTextObservable.asObservable()
            //wait 0.3 s after the last value to fire a new value
            .debounce(0.0, scheduler: MainScheduler.instance)
            //only fire if the value is different than the last one
            .distinctUntilChanged()
            //convert Observable<String> to Observable<Weather>
            .flatMapLatest { searchString -> Observable<[AnyObject]> in
                return TPReactiveDatabase.sharedInstance.searchPlacesByTitle(searchString)
            }
            //make sure all subscribers use the same exact subscription
            .shareReplay(1)

和包装器方法searchPlacesByTitle

class TPReactiveDatabase: NSObject {

    static let sharedInstance = TPReactiveDatabase()

    // MARK: - Reactive Place database

    func searchPlacesByTitle(title: String) -> Observable<[AnyObject]> {
        return Observable.create { observer in

            var places = [AnyObject]()

            if (title.characters.count > 0) {
                places = DBAccessKit.searchPlacesByTitle(title)
            }

            observer.on(.Next(places))
            observer.on(.Completed)

            return AnonymousDisposable {

            }
        }
    }
}
点赞