2016-08-24 2 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) 
    } 
} 

그리고 내보기 모델 : - [Place]

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] 있습니다. 내 ViewModel의 flatMapLatest에 어디서 어떻게 배치했는지 이해할 수 없습니다.

+0

당신이 RxSwift의 환매 특약의 [RxExample] (https://github.com/ReactiveX/RxSwift) 프로젝트를 확인 했습니까? – KhanXc

+0

@KhanXc 예. 이제 RxDelegates를 사용하고 싶지 않습니다. 너무 많은 새로운 프레임 워크. 그래서 나는 그것들없이 해결책을 찾고 싶다. –

+0

대리자 중 일부가 내장되어 있습니다 (RxDatasource를 사용하지 않는 경우). RxExample의 위키 피 디아 이미지 검색 코드는 사용자의 목적에 맞을 것입니다. 옵저버 대신 드라이버를 사용합니다. – KhanXc

답변

1

Observable < [장소]>를 작성하여 내 데이터베이스에 반응 형 래퍼를 만듭니다.

이 내 코드

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 { 

      } 
     } 
    } 
}