MVVM and RxSwift for search screen

In order to create MVVM and RxSwift, I want to create a simple search screen that will look like a table and a search bar. When the user enters something into the search bar, I will show what he has in this table. It sounds pretty simple, but I can't find a tutorial that suits me.

I already wrote all the code in the controller, I just can’t understand what you need to observe changes to the search text, and then call the database method, which will filter the elements by the search text.

Some code that I already have.

My 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)
    }
}

And my look model:

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)
    }

}

In addition, I have a method [DataBase searchPlaces:searchText]that returns an array from places - [Place]. I cannot figure out where and how to place it in flatMapLatestmy ViewModel.

+4
1

, Observable < [Place] > .

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 {

            }
        }
    }
}
+1

Source: https://habr.com/ru/post/1652279/


All Articles