I'm trying to create an observable sequence to indicate the status of Bluetooth on device. I'm using ReplaySubject<CBManagerState>
, but am curious if there is something better, as I hear bad things about using onNext()
What is the appropriate way to connect callback delegates to the RxSwift observable domain?
class BluetoothStatusMonitor: NSObject, CBPeripheralManagerDelegate {
let bluetoothStatusSequence = ReplaySubject<CBManagerState>.create(bufferSize: 1)
var bluetoothPeripheralManager: CBPeripheralManager?
func checkBluetoothStatus()
{
//silently check permissions, without alert
let options = [CBCentralManagerOptionShowPowerAlertKey:0]
bluetoothPeripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: options)
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
bluetoothStatusSequence.onNext(peripheral.state)
}
}
This is exactly the kind of things that Subjects are good for. They exist primarily to convert non-Rx code into Rx code. That said, RxCocoa has the
DelegateProxy
type that is designed to handle a lot of the work necessary to do delegates right. It's still hard to figure out exactly how to implement one, but once you get the hang of it they are quite useful...I have to admit that most of the code is black magic to me, but it does work. I try to explain as much as I can in comments below.
As far as I can tell, the
methodInvoked
function performs some meta-programming magic on the object to install the method at runtime. This is done because many of the iOS classes that have delegates actually behave differently depending on whether or not the method was defined on the delegate (regardless of what the method does,) so we don't want to simply give the proxy every method in the protocol.Of course, once you have the above in place. You can do all the standard RX stuff with your peripheral manager: