2016-08-24 56 views
4

在教育MVVM和RxSwift我想建立簡單的搜索界面,這將有一個表,視圖和搜索欄的目的。當用戶在搜索欄中輸入內容時,我會顯示他在此​​表中的內容。聽起來很簡單,但我找不到適合我的任何教程。MVVM和RxSwift的搜索屏幕

我已經寫在視圖控制器的所有代碼,我只是不明白必須遵守的搜索文本的修改,然後調用數據庫的方法,這將通過過濾搜索文本的項目。

一些代碼,我已經有了。

我的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

+0

你檢查在RxSwift回購的[RxExample(https://github.com/ReactiveX/RxSwift)項目? – KhanXc

+0

@KhanXc是的。我現在不想使用他們的RxDelegates。太多新的框架。這就是爲什麼我想找到解決方案沒有他們。 –

+0

某些代表是內置的(除非您使用的是RxDatasource)。來自RxExample的維基百科圖像搜索代碼將適合您的目的。它使用驅動程序而不是觀察者。 – KhanXc

回答

1

我通過創建可觀察< [地方]>創建我的數據庫活性包裝。

這是我的代碼

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 { 

      } 
     } 
    } 
}