2017-03-23 7 views
1

サードパーティのライブラリを使用している場合があり、オブザーバブルにしたいと考えています。適切に、図書館は代表者の周りに設計されているので、私はそれをラッピングしています。ライブラリは、非同期操作を実行し、完了したらその結果を持つ代理人を呼び出します。サードパーティのライブラリデリゲートをRxSwift Observableに正しく変換する方法

私は間違いなく観測可能な性質のcoldを利用したいと思っており、誰かが購読したときに操作を開始するだけです。私には解決策がありますが、深刻な欠陥があるかどうか分かりませんし、RxSwiftの重要な理解が不足しているか、同じ目標を達成するための簡単な方法があるかもしれません。

public final class RxLibBridge: LibDelegate{ 

    let lib = Lib() 
    let _source = PublishSubject<[LibResult]>() 

    public init(){ 
     lib.delegate = self 
    } 

    public func asObservable() -> Observable<[LibResult]>{ 
     // create a cold observable to start 
     // the Lib's async operation on subscribe. 
     return Observable<Void>.create{ 
      observer in 

      self.lib.startOperation() 

      // emit and complete 
      observer.onNext(()) 
      observer.onCompleted() 
      return Disposables.create() 
     } 
     // convert the `Void` observable into an observable from the 
     // PublishSubject 
     .flatMapLatest{self._source} 
    } 

    // the lib's completion delegate method 
    public func lib(_ lib: Lib, didFinishWithResult results: [LibResult]) { 
     // grab the PublishSubject, emit the result and complete 
     let observer = _source.asObserver() 
     observer.onNext(results) 
     observer.onCompleted() 
    } 
} 

私の質問は、これはRxの適切なパターンですか?再び、それは動作します:

RxLibBridge() 
    .asObservable() 
    .subscribe(...) 

私は基本的にこの状況で適切な方法を誤解していないわけではありません。

私はこのような何か処理するRxSwiftで方法がある知っている:

https://medium.com/@maxofeden/rxswift-migrate-delegates-to-beautiful-observables-3e606a863048#.rksg2ckpj

https://samritchie.net/2016/05/12/rxswift-delegateproxy-with-required-methods/

私はこのアプローチを試みたが、それはで、つまり2015年以降に変更APIのように見えますが、拡張子にrx_delegateメソッドを追加すると、proxyForObjectのリンクの例が見つかりません。

さらに、このアプローチは純粋なObjective-C [UIKit/AppKit] APIを好むようです。リンクされた例に従う私の試みでは、代理メソッドoptionalを作成し、それを@objcに公開するように、第三者libのソースを編集していました。 libの代理人はrequiredです。私はlibを変更して変更する必要はありません。

このSO上記2つのリンクのために更新APIを提供答え:これはRxSwift 3.3.1のために更新され、必要なデリゲートメソッド、とトリックを行いますのようなので、いくつかのより多くを掘った後、それが見えます

https://stackoverflow.com/posts/38326538/edit

答えて

2

。これは、DelegateProxyシステムを使用しています。

import RxSwift 
import RxCocoa 
import Lib 


public final class RxLibDelegate: DelegateProxy, LibDelegate, DelegateProxyType{ 

    let _subject = PublishSubject<[LibResult]>() 

    public static func currentDelegateFor(_ object: AnyObject) -> AnyObject?{ 
     let target = object as! Lib 
     return target.delegate 
    } 

    public static func setCurrentDelegate(_ delegate: AnyObject?, toObject object: AnyObject) { 
     let target = object as! Lib 
     target.delegate = delegate as? LibDelegate 
    } 

    public func lib(_ lib: Lib, didFinishWithResult results: [LibResult]) { 
     _subject.onNext(results) 
     _subject.onCompleted() 
    } 
} 



extension Lib{ 

    public var rx_delegate: DelegateProxy{ 
     // `proxyForDelegate` moved as compared to examples at: 
     // https://samritchie.net/2016/05/12/rxswift-delegateproxy-with-required-methods/ 
     // https://medium.com/@maxofeden/rxswift-migrate-delegates-to-beautiful-observables-3e606a863048#.rksg2ckpj 

     return RxLibDelegate.proxyForObject(self) 
    } 

    public var rx_libResults: Observable<[LibResult]> { 
     // `proxyForDelegate` moved as compared to examples at: 
     // https://samritchie.net/2016/05/12/rxswift-delegateproxy-with-required-methods/ 
     // https://medium.com/@maxofeden/rxswift-migrate-delegates-to-beautiful-observables-3e606a863048#.rksg2ckpj 

     let proxy = RxLibDelegate.proxyForObject(self) 
     return proxy._subject 
    } 
} 

これは約28 LOCです。私のオリジナルの「ラッパー」(下記の更新版を参照)が、21 LOCが最善かどうかわかりません。他の1/6の半分の6?

私の特別なケースでは、私は心配する1つのデリゲートメソッドしかありません。複数のデリゲートを持ついくつかの機能を使って作業していたなら、私はDelegateProxy + extensionの方法がもっと実用的で、その場合にはより良い選択となると思います。ここで明らかなようにVoid観察可能な、それはflatMapLatestで流れを変えるために、完全に許容です表示されていることを使用して私の元裁判ラッピング事について

再:ボタンを押している間、継続的にイベントを送信:

https://stackoverflow.com/a/39123102/1060314

import RxSwift 
import RxCocoa 


let button = submitButton.rx_controlEvent([.TouchDown]) 
button 
.flatMapLatest { _ in 
    Observable<Int64>.interval(0.1, scheduler: MainScheduler.instance) 
     .takeUntil(self.submitButton.rx_controlEvent([.TouchUpInside])) 
} 
.subscribeNext{ x in print("BOOM \(x)") } 
.addDisposableTo(disposeBag) 

//prints BOOM 0 BOOM 1 BOOM 2 BOOM 3 BOOM 4 BOOM 5 for every 0.1 seconds 

flatMapLatestから新しいObservableが返されることに注意してください。作者はRxSwift slack channelを引用しているので、少なくともそれは受け入れられると思います。

ここで私は少しきれいかもしれないと思う私のラッパーバージョンの更新バージョンです:

import RxSwift 


public final class RxLibBridge: LibDelegate{ 

    let lib = Lib() 
    let _source = PublishSubject<[LibResult]>() 

    public init(){ 
     lib.delegate = self 
    } 

    public func asObservable() -> Observable<[LibResult]>{ 
     // create a cold observable to start 
     // the Lib's async operation on subscribe. 
     return Observable.just(()) 
      .do(onNext: { 
       self.lib.startOperation() 
      }) 
      .flatMapLatest{self._source} 
    } 

    // the lib's completion delegate method 
    public func lib(_ lib: Lib, didFinishWithResult results: [LibResult]) { 
     // grab the PublishSubject, emit the result and complete 
     _source.onNext(results) 
     _source.onCompleted() 
    } 
} 
は、
関連する問題