2016-08-24 5 views
4

Im Sinne der Bildung MVVM und RxSwift Ich möchte einfache Suchbildschirm, der eine Tabellenansicht und eine Suchleiste haben wird bauen. Wenn der Benutzer etwas in die Suchleiste eingibt, zeige ich, was er in dieser Tabelle hat. Klingt ziemlich einfach, aber ich kann kein Tutorial finden, das zu mir passt.MVVM und RxSwift für die Suche Bildschirm

Ich habe bereits alle Code in View-Controller geschrieben, ich kann einfach nicht verstehen, müssen Suchtextänderungen beobachten und rufen Sie dann Datenbank-Methode, die Elemente nach Suchtext filtern wird.

Einige Code, den ich bereits habe.

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

Und meiner Meinung nach Modell:

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

} 

Auch habe ich Methode [DataBase searchPlaces:searchText] das Array von Orten gibt - [Place]. Ich kann nicht verstehen, wo und wie es in flatMapLatest meines ViewModel platziert.

+0

Haben Sie die [RxExample] (https://github.com/ReactiveX/RxSwift) Projekt in RxSwift Repo? – KhanXc

+0

@KhanXc ja. Ich möchte ihre RxDelegates jetzt nicht benutzen. Zu viele neue Frameworks. Deshalb möchte ich ohne sie eine Lösung finden. –

+0

Einige der Delegierten sind integriert (es sei denn, Sie verwenden RxDatasource). Der Wikipedia-Bildsuchcode von RxExample wird Ihrem Zweck entsprechen. Er verwendet Treiber anstelle von Beobachtern. – KhanXc

Antwort

1

Ich erstelle reaktive Wrapper für meine DataBase durch Erstellen von Observable < [Ort]>.

Dies ist mein Code

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) 

Und Wrappermethode 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 { 

      } 
     } 
    } 
}