2017-02-27 25 views
0

MVxパターンを使用してRxSwiftをコードに追加しようとしています。私のアプリは、APIからFoodType(砂漠、食事など)のリストを取得してRealmデータベースに保存する必要があります。次に、私はUITextFieldとUIButtonを持つビューを持っています。RxSwiftを使用した非同期API呼び出し後のビューの更新

ユーザーは、食品の種類、書き込みボタンクリックでアプリがAPIからFoodTypeとFoodListを取得する必要がない場合はレルムでDB

  • ::(例:砂漠):

    • 背景をその食品のショーのリストをFoodTypeレルム

    ビューモデル

    struct FoodTypeViewModel { 
    
        // Get datas from API 
        private func getFoods() { 
         foodService.getAll(completionHandler: { result in 
          switch result { 
          case .Success(let foods): 
           for food in foods { 
            food.save() 
           } 
           break 
          case .Failure(let error): 
           debugPrint(error) 
           break 
          } 
         }) 
        } 
    
        // Get datas from API 
        private func getFoodTypes() { 
         foodService.getAll(completionHandler: { result in 
          switch result { 
          case .Success(let foodTypes): 
           for type in types { 
            type.save() 
           } 
           break 
          case .Failure(let error): 
           debugPrint(error) 
           break 
          } 
         }) 
        } 
    } 
    
    からユーザが選択しました

    のViewController

    class SetupViewController: UIViewController { 
         @IBOutlet weak var foodTypeTextField: UITextField! 
         @IBOutlet weak var foodTypeButton: UIButton! 
    } 
    

    モデル

    class FoodType: Object { 
        dynamic var identifier: String = "" 
        dynamic var fullName: String? 
        let foods = List<Food>() 
    } 
    

    私は、そのコードにRxSwiftを追加したいが、どのように私は、非同期APIを扱うことができます。最初の起動時には、アプリケーションにはデータがありません(私は開始時には挿入したくありません)が、ユーザーがボタンをクリックするとデータがありません。したがって、ボタンをクリックすると、UIは待機アニメーションを使用してサービスからの応答を待機し、サービスが応答するとViewModelはUIを更新する必要があります。何か案が ?

  • 答えて

    1

    まず、通信エラーをラップするための汎用の戻りオブジェクトを作成します。

    enum APIResult<T> { 
        case success(T) 
        case error(Error) 
    } 
    

    その後、Observableを返すために、あなたの完了ハンドラを変換:

    func getFoods() -> Observable<APIResult<[FoodType]>> { 
        return Observable<APIResult<[FoodType]>>.create { observer -> Disposable in 
         self.foodService.getAll(completionHandler: { result in 
          switch result { 
          case .Success(let foods): 
           observer.onNext(.success(foods)) 
           break 
          case .Failure(let error): 
           observer.onNext(.error(error)) 
           break 
          } 
          observer.onCompleted() 
    
          return Disposables.create() 
         }) 
        } 
    } 
    

    は今、単にRxSwiftに他のように観察を処理します。 these utility classesを使用して

    getFoods().subscribe(onNext: { result in 
        switch result { 
         case .success(let foods): 
          print("Received foods: \(foods)") 
          break 
         case .error(let error): 
          print("Received error: \(error)") 
          break 
        } 
    }.addDisposableTo(disposeBag) 
    

    あなたが別の観測に成功した結果と分割エラーと成功信号をマッピングするのに役立ちます。たとえば:

    let foodsRequest = getFoods().splitSuccess 
    
    foodsRequest.error.subscribe(onNext: { error in 
        print("Received error: \(error)") 
    }) 
    
    foodsRequest.success.subscribe(onNext: { foods in 
        print("Received foods: \(foods)") 
    } 
    

    また、レルムがRxSwiftの観測にオブジェクトを変換することができます:

    let realm = try! Realm() 
    realm.objects(Lap).asObservable() 
        .subscribeNext {[weak self] laps in 
        self?.tableView.reloadData() 
        } 
    

    は、より多くの情報と例についてUsing Realm Seamlessly in an RxSwift Appを見てみましょう。

    +0

    ありがとうございますが、それは領域を処理する最善の方法ですか?つまり、アプリの生活の中でローカルストレージのみを使用する方法があると私は考えました。 APIはDBとのみ通信し、ビューはDBの変更に反応します。あなたの場合、私はAPIからのデータを待つべきです。私が何を意味するのか理解していますか? Btw、この非常に良い答えとクラスのおかげで! – Ludovic

    +1

    @ルドビックローカルデータベースの変更を観測可能ファイルとしてバインドすることもできます。私の編集を見てください。 – redent84

    +0

    お返事ありがとうございます! – Ludovic

    関連する問題