Search code examples
iosreactive-programmingcore-bluetoothrx-swift

iOS RxSwift 4.2 how to implement Reactive extension of CBCentralManager using DelegateProxy?


I'm looking at this example of using reactive extensions with Core Bluetooth. However, it is written in swift 3.0 and has a number of errors running in Swift 4.2. I'm interested in implementing a reactive extension of CBCentralManager to provide me with a RX stream of status events.

My understanding is that this allows the proxy to receive delegate events from the CBCentralManager and propagate them to observers using _stateBehaviorSubject: BehaviorSubject<CBManagerState>? However, the project has too many errors and I cannot figure out where do I cut to keep only the functionality I want.

How do I implement the a reactive extension using DelegateProxy for CBCentralManager?

extension Reactive where Base: CBCentralManager {

  public var delegate: DelegateProxy {
    return RxCBCentralManagerDelegateProxy.proxyForObject(base)
  }

  public var state: Observable<CBManagerState> {
    let proxy = RxCBCentralManagerDelegateProxy.proxyForObject(base) //error here
    return proxy.stateBehaviorSubject.skip(1)
  }
}

Solution

  • This is a working implementation for CBCentralManager

    extension CBCentralManager : HasDelegate {
        public typealias Delegate = CBCentralManagerDelegate
    }
    
    class RxCBCentralManagerDelegateProxy
      : DelegateProxy<CBCentralManager, CBCentralManagerDelegate>
      , DelegateProxyType
      , CBCentralManagerDelegate
    {
    
       internal let stateBehaviorSubject: BehaviorSubject<CBManagerState>
    
       init(centralManager: CBCentralManager) {
           let subject = BehaviorSubject(value: centralManager.state)
           stateBehaviorSubject = subject
    
           super.init(parentObject: centralManager, delegateProxy: RxCBCentralManagerDelegateProxy.self)
       }
    
       func centralManagerDidUpdateState(_ central: CBCentralManager) {
           stateBehaviorSubject.onNext(central.state)
           _forwardToDelegate?.centralManagerDidUpdateState(central)
       }
    
       static func registerKnownImplementations() {
           self.register { RxCBCentralManagerDelegateProxy(centralManager: $0) }
       }
    
       deinit {
           stateBehaviorSubject.on(.completed)
       }
    }
    
    extension Reactive where Base : CBCentralManager {
       var delegate: DelegateProxy<CBCentralManager, CBCentralManagerDelegate> {
           return RxCBCentralManagerDelegateProxy.proxy(for: base)
       }
    
       var state: ControlEvent<CBManagerState> {
           let source = (delegate as! RxCBCentralManagerDelegateProxy)
              .stateBehaviorSubject
              .skip(1)
           return ControlEvent(events: source)
       }
    }