0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RxSwift Firebase RemoteConfig データ取得メモ

Last updated at Posted at 2020-01-21

Firebase RemoteConfig のデータを取得するためのメモ 

メモなので今後も追記予定
Jsonを保存しておいてパースして使う


protocol ViewModelInputs {
    var fetchTrigger: PublishSubject<Void> { get }
}

protocol ViewModelOutputs {
    var items: Observable<[Item]> { get }
    var isLoading: Observable<Bool> { get }
    var error: Observable<ActionError> { get }
}

protocol ViewModelType {
    var inputs: ViewModelInputs { get }
    var outputs: ViewModelOutputs { get }
}


class ViewModel: ViewModelInputs, ViewModelOutputs, ViewModelType {

    var inputs: ViewModelInputs { return self }
    var outputs: ViewModelOutputs { return self }

    // MARK: - Inputs
    let fetchTrigger = PublishSubject<Void>()
    
    // MARK: - Outputs
    let items: Observable<[Item]>
    let isLoading: Observable<Bool>
    let error: Observable<ActionError>

    // 内部変数
    private let status = BehaviorRelay<RemoteConfigFetchStatus>(value: .noFetchYet)
    private let itemJson = RemoteConfig.remoteConfig().configValue(forKey: "xxx_json")
    private let configAction: Action<(), RemoteConfigFetchStatus>
    private let disposeBag = DisposeBag()

    init() {
        
        // Actionを定義 
        self.configAction = Action { _ in
            return RemoteConfig.remoteConfig().rx
            .fetch(withExpirationDuration: TimeInterval(180), activateFetched: true)
        }
        
        // 実行結果をbind
        self.configAction.elements
            .bind(to: status)
            .disposed(by: disposeBag)
        
        // 一時的な変数
        let tmpItems    = BehaviorRelay<[Item]>(value: [])
        // Observableをoutputs変数へ
        self.items      = tmpItems.asObservable()
        
        self.status
            .filter { $0 == RemoteConfigFetchStatus.success } // 接続成功時のみ
            .withLatestFrom(Observable.of(itemJson.stringValue)) // データ取得
            .filterNil()
            .compactMap { $0.data(using: .utf8) }
            .compactMap { data in
                // Jsonを解析して配列を生成
                do {
                    return try (JSONSerialization.jsonObject(with: data, options: []) as? [[String : Any]])?.compactMap { Item(json: JSON($0)) }
                } catch {
                    return []
                }
            }
        .bind(to: tmpItems)
        .disposed(by: disposeBag)

        // ローディング 初期値はfalse
        self.isLoading = self.configAction.executing.startWith(false)

        // エラー
        self.error = self.configAction.errors
        
        // 開始
        self.fetchTrigger
            .bind(to: self.configAction.inputs)
            .disposed(by: disposeBag)
    }
}

こんなふうにして使う

        self.viewModel = ViewModel()

        // Firebase Remote Config へ接続
        self.viewModel.inputs.fetchTrigger.onNext(())
        
        // FireBase から データを取得してテーブルに表示
        self.viewModel.outputs.items.asObservable()
            .subscribe(onNext:{ [unowned self] items in
                self.items = items
                self.tableView.reloadData()  // DataSourceもRxにするとさらに楽
            }).disposed(by: rx.disposeBag)
        
        // ローディング 
        self.viewModel.isLoading.asDriver(onErrorJustReturn: false)
            .drive(SVProgressHUD.rx.isAnimating())
            .disposed(by: rx.disposeBag)
        
        // エラー表示
        self.viewModel.outputs.error
            .subscribe(onNext: { [unowned self] error in
                // アラートとかで表示する
                print(error.localizedDescription)
            }).disposed(by: rx.disposeBag)

ついでにこんなのを作ってローディング中に表示する
trueで表示、falseで非表示
Actionのexecutingが実行中にtrueを流すのでそのまま表示

import UIKit
import SVProgressHUD
import RxSwift
import RxCocoa

extension Reactive where Base: SVProgressHUD {
    static func isAnimating() -> AnyObserver<Bool> {
        return AnyObserver { event in
            MainScheduler.ensureExecutingOnScheduler()
            switch event {
            case .next(let value):
                if value {
                    SVProgressHUD.show()
                } else {
                    SVProgressHUD.dismiss()
                }
            default:
                break
            }
        }
    }
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?