iOS & OSX Bluetooth library for RxSwift

Overview

RxBluetoothKit library logo

CI Status Platform Carthage Compatible

RxBluetoothKit is a Bluetooth library that makes interaction with BLE devices much more pleasant. It's backed by RxSwift and CoreBluetooth and it provides nice API, for both Central and Peripheral modes. All to work with and make your code more readable, reliable and easier to maintain.

Here is a sneak peek of what you can do with RxBluetoothKit:

manager.scanForPeripherals(withServices: [serviceId])
    .take(1)
    .flatMap { $0.peripheral.establishConnection() }
    .flatMap { $0.discoverServices([serviceId]) }
    .flatMap { Observable.from($0) }
    .flatMap { $0.discoverCharacteristics([characteristicId]) }
    .flatMap { Observable.from($0) }
    .flatMap { $0.readValue() }
    .subscribe(onNext: { print("Value: \($0.value)") })

With just 9 lines it started scanning, connecting to the peripheral, discovering service and characteristics and read charecteristic's value!

Central mode features

Peripheral mode features

  • Observing manager states
  • Advertising
  • Observing read & writes
  • Observing subscribe
  • Publishing L2CAP channels
  • And a lot more!

Recent Changes

6.0.0

  • Increased deployment target for iOS to 9.0 and for osx to 10.13 (#379, #380)
  • Added support for observing ancsAuthorized property on peripheral. (#370)
  • Added Bluetooth usage description to Info.plist in Example project (#369)
  • Added initial state improvement & a minor fix for BluetoothState methods. (#371)
  • Fixed problems with SPM support (#358, #368)
  • Updated RxSwift version to 5.1 (#376)
  • Updated project configurations to decrease build time on TravisCI (#376)
  • Updated scripts to fixed problems with generating mocks (#378)

All previous changes

Want to migrate from 4.x to 5.x? Check guidelines here.

Installation

CocoaPods

CocoaPods is a dependency manager for CocoaProjects. To integrate RxBluetoothKit into your Xcode project using CocoaPods specify it in your Podfile:

pod 'RxBluetoothKit'

Then, run the following command: $ pod install

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate RxBluetoothKit into your Xcode project using Carthage specify it in your Cartfile:

github "Polidea/RxBluetoothKit"

Then, run carthage update to build framework and drag RxBluetoothKit.framework into your Xcode project.

Swift Package Manager

Versions >= 4.0 of the library integrate with the Swift Package Manager. In order to do that please specify our project as one of your dependencies in Package.swift file.

Getting Started

Check our Wiki with guidelines to (almost) all library functionalites.

Documentation & Support

Remember to follow Polidea's Blog blog to get all the news and updates!

Contact us

Learn more about Polidea's BLE services here.

Requirements

  • iOS 9.0+
  • OSX 10.13+
  • watchOS 4.0+
  • tvOS 11.0+
  • Xcode 11.4+

Swift versions

  • 3.0 version supports Swift 3.0 and 3.1
  • 5.0 version supports Swift 3.2 and 4.0
  • 5.1.2 version supports Swift 4.1
  • 5.2 version supports Swift 5.0 and 4.2
Comments
  • Cannot subscribe to Observable<Characteristic> - timeout error.

    Cannot subscribe to Observable - timeout error.

    I have a problem with subscribe multiple different characteristic types in my application. At first I connect to the device and declare Observable values

    let peripheralObservable <- let with information about connected device
    let dataStream1Observable = peripheralObservable
            .flatMap { (peripheral) -> Observable<Characteristic> in
                return peripheral.setNotificationAndMonitorUpdates(for: "some ID")
            }.map { (characteristic) -> Data? in
                return characteristic.value
            }
        let isConnectedObservable = peripheralObservable
            .flatMap { (peripheral: Peripheral) -> Observable<Bool> in
                return peripheral.rx_isConnected
            }
    
    

    Then I subscribed first value (isConnectedObservable), everything works good. Next I call dispose on this subscribtion and start new one on dataStream1Observable, then I wait a moment and I get error "timeout error". What I do wrong? It is a error in my application or in this library. I really need help.

    opened by mxndev 22
  • retrieveConnectedPeripherals is not working for orphan connections. Does it need options?

    retrieveConnectedPeripherals is not working for orphan connections. Does it need options?

    Hello, I'm fighting an issue currently involving "orphan" connections, where the app has disconnected however iOS is maintaining the physical link indefinitely until the peripheral power is disconnected. This has the effect of not only making the peripheral unable to be connected to again by the app, but also blocking all other devices from seeing it when scanning.

    While trying to fix the underlying issue I updated my scan code to check if one of our devices was already connected before beginning a scan. The issue I'm having is retrieveConnectedPeripherals is returning no devices even when in this "orphan" state. The Observable<[Peripheral]> array is always [].

    Looking at the CoreBluetooth method: centralManager.retrieveConnectedPeripherals(withServices: serviceUUIDs).map(RxCBPeripheral.init))

    The documentation says: "The list of connected peripherals can include those that are connected by other apps and that will need to be connected locally using the connect(_:options:) method before they can be used."

    Yet I don't see a way to pass those options in, which seems important if the method is supposed to return a peripherial. It's possible this is not related to why it's not working, but I thought I would ask.

    Thanks in advance for any help you can offer!

    opened by RamblinWreck77 21
  • Issue writing and reading chunked

    Issue writing and reading chunked

    Hi, Ive been trying to write (chunked) and read large values, found some stuff in the issues but still no luck here is what Im doing now, it never reaches to step2 of handshake Thanks in advance, love the project btw.

    override func viewDidLoad() {
        super.viewDidLoad()
    
        manager.rx_state
            .filter { $0 == .poweredOn }
            .take(1)
            .flatMap { _ in self.manager.scanForPeripherals(withServices: nil) }
            .filter { $0.peripheral.name == "TT 3015" }.take(1)
            .flatMap { $0.peripheral.connect() }
            .flatMap { MTKHandshakeProcessor(peripheral: $0).process(libCommand: self.libCommand) }
            .subscribe(onNext: { response in
                print("NEXT -> \(response.data.utf8String ??? "")")
            }).addDisposableTo(disposeBag)
    }
    
    enum MTKHandshake {
        case step1
        case step2
        
        func payload(libCommand: LibCommandGateway) -> Data {
            switch self {
            case .step1: return libCommand.dataCommand(2, command: "REQV")
            case .step2: return libCommand.dataCommand(2, command: "0 8 1.1 IOS")
            }
        }
    }
    
    
    struct MTKHandshakeProcessor {
        let peripheral: Peripheral
        
        init(peripheral: Peripheral) {
            self.peripheral = peripheral
        }
        
        func process(libCommand: LibCommandGateway) -> Observable<CommandResult> {
            let processor = MTKResponseProcessor()
            let handler = { (data: Data) in
                processor.findCommandResponse(data: data, libCommand: libCommand)
            }
            
            return peripheral
                .writeAndRead(data: MTKHandshake.step1.payload(libCommand: libCommand), untilFound: handler)
                .flatMap { _ in self.peripheral.writeAndRead(data: MTKHandshake.step2.payload(libCommand: libCommand), untilFound: handler) }
        }
        
    }
    
    struct CommandResult {
        let data: Data
    }
    
    extension Peripheral {
    
        func writeChunked(writer: Characteristic, data: Data) -> Observable<Characteristic> {
            let chunks = data.chunked(byMaxSize: maximumWriteValueLength(for: .withResponse))
            return Observable.from(chunks).flatMap { writer.writeValue($0, type: .withResponse) }
        }
        
        func writeAndRead(data dataToSend: Data, untilFound: @escaping ((Data) -> BinaryCommand?)) -> Observable<CommandResult> {
            
            let pendingData = NSMutableData()
            
            // This observable will take care of accumulating data received from notifications
            let result = characteristic(with: MTKDeviceCharacteristic.read)
                .flatMap { $0.monitorValueUpdate() }
                .takeWhile { characteristic in
                    return untilFound(pendingData as Data) != nil
                }
                .reduce(pendingData, accumulator: { (data, characteristic) -> NSMutableData in
                    if let packetData = characteristic.value {
                        data.append(packetData)
                    }
                    return data
                })
            
            
            let writes = characteristic(with: MTKDeviceCharacteristic.write)
                .flatMap { self.writeChunked(writer: $0, data: dataToSend) }
            
            return Observable.zip(result, writes, resultSelector: { (result: NSMutableData, query: Characteristic) -> CommandResult in
                return CommandResult(data: result as Data)
            })
        }
    }
    
    extension Data {
        func chunked(byMaxSize: Int) -> [Data] {
            return (self as NSData).dataChunks(ofSize: UInt(byMaxSize))
        }
    }
    
    
    
    opened by MarvinNazari 18
  • Act on disconnect or bluetooth state changes

    Act on disconnect or bluetooth state changes

    Hi,

    Thanks for this awesome work.

    I'm having some trouble to find a way to correctly restore my device connection if any disconnect or bluetooth state trigger an error.

    It's probably due to my skill level in Rx but I would love your insights.

    I'm trying to create a Device object which will wrap the logic of waiting for correct BLE state, scan for peripheral, connect to one with specific name, detect services & characteristics, listen to some notification and then republish the notification using some PublishSubject to be consume by my controller (or what ever else).

    The issues is that I would like to reconnect all of this if any error occurs (like device disconnection, ble state changes, ...).

    This code have some trivial issues, like subscribing twice to the characteristics, but I can figure out how to not do it, if I use a simple share on characteristics and the retry on my notification it won't work.

    I'm having trouble wrapping my head around this...

    class Device {
        let measure = PublishSubject<Data>()
        let alert = PublishSubject<Data>()
        
        private let disposeBag = DisposeBag()
        
        init(name: String) {
            let manager = BluetoothManager(queue: .main)
            
            let queue = DispatchQueue(label: "fr.xdev.rxbluetoothkit.bluetooth")
            let scheduler = SerialDispatchQueueScheduler(queue: queue, internalSerialQueueName: "")
            
            let characteristics = manager.rx_state
                .filter { $0 == .poweredOn }
                .take(1)
                .flatMap { _ in manager.scanForPeripherals(withServices: [.common(.main)]) } // extension on CBUUID
                .filter { $0.peripheral.name == name }
                .take(1)
                .flatMap { $0.peripheral.connect() }
                .flatMap { $0.discoverServices([.common(.main)]) } // extension on CBUUID
                .flatMap { Observable.from($0) }
                .flatMap { $0.discoverCharacteristics([.common(.measure), .common(.protection)]) } // extension on CBUUID
                .flatMap { Observable.from($0) }
            
            characteristics
                .filter { $0.uuid.type == .measure } // extension on CBUUID
                .flatMap { $0.setNotificationAndMonitorUpdates() }
                .map { $0.value }
                .unwrap() // ignore nil value
                .retryWithDelay(5) // !!!: retry and resubscribe to the full chain on error
                .subscribe(onNext: { [unowned self] data in
                    self.measure.onNext(data!)
                })
                .disposed(by: disposeBag)
            
            characteristics
                .filter { $0.uuid.type == .alert } // extension on CBUUID
                .flatMap { $0.setNotificationAndMonitorUpdates() }
                .map { $0.value }
                .unwrap() // ignore nil value
                .retryWithDelay(5) // !!!: retry and resubscribe to the full chain on error
                .subscribe(onNext: { [unowned self] data in
                    self.alert.onNext(data!)
                })
                .disposed(by: disposeBag)
        }
    }
    

    Here is an extended version of this sample project: https://gist.github.com/huguesbr/41290240fad1a4de290dd3e81305ed96

    Any advices of how to organize this?

    Thanks

    question 
    opened by huguesbr 15
  • Periodical scanning

    Periodical scanning

    Hi everyone, I'm trying to make periodical scan using RxBluetoothKit without success. Can anyone give some directions. I can't find something similar in the docs or sample app. What I want to do is scan for 3 seconds, pause 1 second and start scanning again for 3 seconds and so on.

    Thanks.

    help wanted 
    opened by dneykov 14
  • observeConnection

    observeConnection

    I used to use 4 rx_isConnected for a good time. But with a 5 observeConnection, this will automatically call the disconnected method observeDisconnect after my active connection. I don't know what it was. I'm confused. @minixT

    opened by LiuSky 13
  • Have you removed `listenOnRestoredState` completely?

    Have you removed `listenOnRestoredState` completely?

    The new major release just broke my neck, I'm currently trying to update my app to support it. I used listenOnRestoredState to silent the annoying CoreBluetooth logs, but now this API is gone. My app isn't running yet so I cannot tell for sure if the warning will re-appear.

    opened by DevAndArtist 13
  • scanForPeripherals not returning device after disconnection on iOS11

    scanForPeripherals not returning device after disconnection on iOS11

    Hi,

    Here is my workflow :

    1. scanForPeripherals : got DeviceA
    2. stopScan
    3. manager.connect(DeviceA)
    4. working with device...
    5. manager.cancelPeripheralConnection(DeviceA)
    6. scanForPeripherals : got nothing on iOS11, got DeviceA on iOS10

    Here is some snippet of my code, maybe i'm doing something wrong ?

    func scan(_ delegate: BluetoothClientScanDelegate) {
            scanningDisposable = manager.rx_state
                .filter { $0 == .poweredOn }
                .take(1)
                .flatMap { _ in self.manager.scanForPeripherals(withServices: [BluetoothService.device.uuid], options:nil) }
                .subscribeOn(MainScheduler.instance)
                .subscribe(onNext: { device in
                    delegate.onDeviceFound(device)
                }, onError: { error in
                    delegate.onScanError(error)
                })
        }
    
    func stopScan() {
            scanningDisposable?.dispose()
        }
    
    func connectToDevice(_ device: Peripheral, delegate: BluetoothClientDeviceDelegate) {
            deviceDelegate = delegate
            currentDevice = device
    
            Logger.get().info("Connecting to device...")
    
            let _ = manager.connect(device).subscribe(
                onNext: { _ in
                    Logger.get().info("Connected to device")
                    self.monitorDisconnection()
                    self.setupModeData()
                },
                onError: {
                    Logger.get().error($0)
                    self.deviceDelegate?.onDeviceFailed($0)
                }
            )
        }
    
    func disconnectFromDevice() {
            deviceDelegate = nil
            disconnectionDisposable?.dispose()
            notificationDisposable?.dispose()
            guard let device = currentDevice else {
                return
            }
            currentDevice = nil
            _ = manager.cancelPeripheralConnection(device).subscribe()
        }
    
    opened by Ezor 13
  • init CentralManager with restorationId causes unsupported state

    init CentralManager with restorationId causes unsupported state

    I'm facing a weird issue (version 5.1.0 of this lib): When using the CentralManager without any init option, the observeState() observable is well working.

    But as soon as I add a restore identifier key, the observeState() observable just sends one (and only one) unsupported state, then no more events even after enabling/disabling Bluetooth (either from control center or Settings). As soon as I remove the restoreIdentifier options, it works back again nicely...

    Is there anything wrong I did, or an issue in the lib? Thanks for the help!

    Here is the observe state part that prints everything happening there:

    public func observeBluetoothState() -> Observable<BluetoothState> {
            return manager!.observeState()
                .do(
                    onNext: { newstate in print("RXBT observeState onNext, new state is \(newstate)") },
                    onError: { error in print("RXBT observeState onError, error is \(error)") },
                    onCompleted: { print("RXBT observeState onCompleted") },
                    onSubscribe: { print("RXBT observeState onSubscribe") },
                    onSubscribed: { print("RXBT observeState onSubscribed") },
                    onDispose: { print("RXBT observeState onDispose") }
                )
        }
    

    CentralManager initialization without options:

    var manager = CentralManager(  queue: .main )
    
    /* result output: 
    RXBT observeState onSubscribe
    RXBT observeState onSubscribed
    RXBT observeState onNext, new state is poweredOn
    RXBT observeState onNext, new state is poweredOff
    RXBT observeState onNext, new sRXBT observeState onNext, new state is poweredOff
    RXBT observeState onNext, new state is poweredOn
    RXBT observeState onNext, new state is poweredOff
    RXBT observeState onNext, new state is poweredOn
    */
    

    CentralManager initialization with restore options:

    var manager = CentralManager(  queue: .main,
                                       options: [CBCentralManagerOptionRestoreIdentifierKey:"get.myId.centralManagerRestoreKey" as AnyObject],
                                       onWillRestoreCentralManagerState: {
                                                centralManagerRestoredState in
                                                print("RXBT centralManagerRestoredState is \(centralManagerRestoredState)")
                                                // do any stuff here later... 
                                            }
            )
    
    /* result output: 
    RXBT observeState onSubscribe
    RXBT observeState onSubscribed
    RXBT observeState onNext, new state is unsupported
    */
    
    opened by ghost 12
  • 5.0 .cancelConnection() equivalent?

    5.0 .cancelConnection() equivalent?

    Hello! Congrats on the release!

    I'm in the process of updating to the new API changes now and can't seem to find a replacement for .cancelConnection() on a peripheral.

    Basically this class gets handed a peripheral, calls cancel connection, subscribes, then onNext notifies the app that the disconnect occurred.

    What's the 5.0 way to do this?

    Thanks!

    opened by RamblinWreck77 12
  • Fix stuck service discovery when looking for different services

    Fix stuck service discovery when looking for different services

    Subsequent calls to discoverServices method in Peripheral with different services UUIDs causing it to return an empty sequence instead of success. This happens because after the first call the peripheral already has some discovered services and in the next call the comparison between sets of services identifiers fails if you ask to discover another service

    opened by xtazz 12
  • Read data from charateristics but not work

    Read data from charateristics but not work

    Hello everyone, thank you for the great job with this library 🎉 I used this lib for my app but I facing the following problem: After I received data from 1 charateristics and continued reading another charateristics it got no response. Code: Screen Shot 2022-06-21 at 13 39 40

    Can you check and help me to resolve this issue? Thank!

    opened by fpt-hungnx5 0
  • Characteristics with same CBUUID in different services

    Characteristics with same CBUUID in different services

    Describe the bug I have two services in one peripheral. Service A
    55AA0148-0001-55AA-1461-227D5E1F4C35 with characteristic tx: 55AA0001-0001-55AA-1461-227D5E1F4C35

    Service B 55AA0248-0001-55AA-1461-227D5E1F4C35 with similar characteristic tx: 55AA0001-0001-55AA-1461-227D5E1F4C35

    When I try to observe both tx characteristics, I get only one notification To Reproduce

    typealias ReadCharacteristic = Observable<Data>
    
    public class DefaultCharacteristicsService {
        public let observeConnection: Observable<Bool>
        private let bag = DisposeBag()
        private let peripheral: Peripheral
        private var peripheralObserver: Observable<Peripheral> = .empty()
        private var peripheralSubscription: SerialDisposable
        
        public init(peripheral: Peripheral) {
            self.peripheral = peripheral
            observeConnection = peripheral.observeConnection()
            peripheralSubscription = SerialDisposable()
            peripheralSubscription.disposed(by: bag)
        }
        
        public func start() -> Observable<Bool> {
            peripheralObserver = peripheral.establishConnection().share(replay: 1, scope: .forever)
            peripheralSubscription.disposable = peripheralObserver.subscribe()
            return peripheral.observeConnection()
        }
        
        public func stop() {
            peripheral.manager.manager.cancelPeripheralConnection(peripheral.peripheral)
            peripheralSubscription.disposable.dispose()
        }
    
        public func observeCharacteristic(service: GATTService) -> ReadCharacteristic {
            characteristic(service: service)
                .flatMap {
                    $0.characteristic.properties.contains(.notify) ||
                        $0.characteristic.properties.contains(.indicate) ? $0.observeValueUpdateAndSetNotification() : $0.readValue().asObservable()
                }
                .compactMap { $0.characteristic.value }
                .debug("observeCharacteristic \(service) characteristic")
        }
    
        private func characteristic(service: GATTService) -> Observable<Characteristic> {
            peripheralObserver
                .filter { $0.isConnected }
                .flatMap {
                    $0.discoverServices([service.serviceCBUUID])
                }
                .asObservable()
                .flatMap { Observable.from($0) }
                .flatMap {
                   $0.discoverCharacteristics([service.characteristicCBUUID])
                }
                .asObservable()
                .flatMap { Observable.from($0) }
        }
    }
    
    func test(peripheral: Peripheral) {
            let service = DefaultCharacteristicsService(peripheral: peripheral)
            service.start()
            
            service.observeCharacteristic(service: .init(characteristicCBUUID: CBUUID(string: "55AA0001-0001-55AA-1461-227D5E1F4C35"),
                                                         serviceCBUUID: CBUUID(string: "55AA0148-0001-55AA-1461-227D5E1F4C35"))).subscribe(onNext: {
                print($0.debugDescription)
            }, onError: {
                print($0.localizedDescription)
            }).disposed(by: bag)
            
            service.observeCharacteristic(service: .init(characteristicCBUUID: CBUUID(string: "55AA0001-0001-55AA-1461-227D5E1F4C35"),
                                                         serviceCBUUID: CBUUID(string: "55AA0248-0001-55AA-1461-227D5E1F4C35"))).subscribe(onNext: {
                print($0.debugDescription)
            }, onError: {
                print($0.localizedDescription)
            }).disposed(by: bag)
    }
    

    It print events in first subscription

    Expected behavior It print events in different subscriptions

    Probably problem is here (CharacteristicNotificationManager): https://ibb.co/MCkFKtz

    Environment:

    • All Devices
    • Library version 6.0

    Thank you for your amazing job!

    opened by lynx56 0
  • Passkey for bluetooth dongle

    Passkey for bluetooth dongle

    Describe the bug A clear and concise description of what the bug is.

    To Reproduce Steps to reproduce the behavior:

    1. Go to '...'
    2. Click on '....'
    3. Scroll down to '....'
    4. See error

    Expected behavior A clear and concise description of what you expected to happen.

    Environment:

    • Device: [e.g. iPhone6, Macbook Pro 2018]
    • OS: [e.g. iOS8.1, macOS 10.11]
    • Library version [e.g. 5.1.2]
    • Swift version [e.g. 4.1]
    opened by Nate5916WP 0
  • Disconnect Connection When device lost connection

    Disconnect Connection When device lost connection

    When terminated the app the connection is still restored but when the device lose connection it can't reconnect again

    class BluetoothManager { //MARK: - Singelton static let shared = BluetoothManager()
    //MARK: - Propertise var centralManager: CentralManager!

    //MARK: - Configure Central Manager
    func configureCentralManager() {
        //        let options = [CBCentralManagerOptionRestoreIdentifierKey: "NOUR", CBCentralManagerOptionShowPowerAlertKey: true] as [String: AnyObject]
        
        centralManager = CentralManager(
            options: [CBCentralManagerOptionRestoreIdentifierKey: NSString("NOUR")],
            onWillRestoreCentralManagerState: { (restoreState) in
                print("RESTORED")
                print(restoreState.centralManager )
            })
    }
    
    //MARK: - Start Scanning For Peripherals
    func startScanningForPeripherals() {
        _ = centralManager.observeState()
            .startWith( centralManager.state )
            .filter { $0 == .poweredOn }
            .flatMap { _ in self.centralManager.scanForPeripherals(withServices: [self.beaconServiceCBUUID]) }
            .subscribe(onNext: { [weak self] scannedPeripheral in
                guard let self = self else { return }
                self.configureScannedPeripherals(scannedPeripheral: scannedPeripheral)
            }, onError: { [weak self] error in
                guard let self = self else { return }
               print("\(error)")
                
            })
    }
    
    //MARK: - Connect To Peripheral Devices
    func connectToPeripheralDevices(peripheral: Peripheral) {
        peripheral.establishConnection()
            .flatMap { $0.discoverServices(nil) }.asObservable()
            .flatMap { Observable.from($0) }
            .flatMap { $0.discoverCharacteristics(nil)}.asObservable()
            .flatMap { Observable.from($0) }
            .filter({ $0.properties.contains(.read) })
            .flatMap { $0.readValue() }
            .subscribe(onNext: {
                let data = $0.value
            }, onError: { error in
                print(error)
            }).disposed(by: disposeBag)
     }
    

    }

    // In App Delegate func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { BluetoothManager.shared.configureCentralManager() }

    opened by andrewehab 0
Releases(6.0.0)
Owner
Polidea
Polidea
RxSwift bindings for Permissions API in iOS.

RxPermission RxSwift bindings for Permission API that helps you with Permissions in iOS. Installation RxPermission is available through CocoaPods. I c

Luke 230 Dec 27, 2022
Super Simple Pager with RxSwift extension

SSPager Super Simple Pager Example To run the example project, clone the repo, and run pod install from the SSPagerExample directory first. Installati

9oya 4 Jul 10, 2022
RxSwift extentions for Swift optionals and "Occupiable" types

RxOptional RxSwift extentions for Swift optionals and "Occupiable" types. Usage All operators are available on Driver as well unless otherwise marked.

Thane Gill 8 Jun 28, 2020
RxSwift wrapper around the elegant HTTP networking in Swift Alamofire

RxAlamofire RxAlamofire is a RxSwift wrapper around the elegant HTTP networking in Swift Alamofire. Getting Started Wrapping RxSwift around Alamofire

RxSwift Community 1.6k Jan 3, 2023
RxSwift extension for RealmSwift's types

RxRealm This library is a thin wrapper around RealmSwift ( Realm Docs ). Table of contents: Observing object collections Observing a single object Wri

RxSwift Community 1.1k Jan 6, 2023
A testable RxSwift wrapper around MultipeerConnectivity

A testable RxSwift wrapper around MultipeerConnectivity RxMultipeer is a RxSwift wrapper for MultipeerConnectivity. Using the adapter pattern, we can

RxSwift Community 69 Jul 5, 2022
RxSwift reactive wrapper for view gestures

RxGesture Usage To run the example project, clone the repo, in the Example folder open RxGesture.xcworkspace. You might need to run pod install from t

RxSwift Community 1.3k Dec 30, 2022
Handy RxSwift extensions on NSObject, including rx.disposeBag.

NSObject+Rx If you're using RxSwift, you've probably encountered the following code more than a few times. class MyObject: Whatever { let disposeBag

RxSwift Community 625 Dec 12, 2022
RxSwift extensions for Core Data

RxCoreData Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Xcode 9.0 Swift 4.0

RxSwift Community 164 Oct 14, 2022
🤖 RxSwift + State Machine, inspired by Redux and Elm.

RxAutomaton RxSwift port of ReactiveAutomaton (State Machine). Terminology Whenever the word "signal" or "(signal) producer" appears (derived from Rea

Yasuhiro Inami 719 Nov 19, 2022
STDevRxExt contains some extension functions for RxSwift and RxCocoa which makes our live easy.

STDevRxExt Example To run the Example.playground, clone the repo, and run pod install from the Example directory first. Requirements iOS 9.0+ tvOS 9.0

STDev 6 Mar 26, 2021
RxAlamoRecord combines the power of the AlamoRecord and RxSwift libraries to create a networking layer that makes interacting with API's easier than ever reactively.

Written in Swift 5 RxAlamoRecord combines the power of the AlamoRecord and RxSwift libraries to create a networking layer that makes interacting with

Dalton Hinterscher 9 Aug 7, 2020
Support Combine Assign subscriber in RxSwift.

RxAssign Support Combine Assign subscriber in RxSwift. Assign uses a KeyPath which is really nice and useful. ** RxAssign extends Driver and Signal in

Won Heo 3 Dec 7, 2021
This is the demo of MVVM-C structure with dependency injection using RxSwift.

MVVMC-Demo Demo defination This is the demo project, I have integrated two APIs for MovieDB APIS (https://www.themoviedb.org/). One for the listing of

Anshul Shah 61 Dec 6, 2022
🎌 Powerful navigation library for iOS based on the coordinator pattern

⚠️ We have recently released XCoordinator 2.0. Make sure to read this section before migrating. In general, please replace all AnyRouter by either Uno

QuickBird Studios 2k Dec 30, 2022
A super simple library for state management with unidirectional data flow.

OneWay ?? OneWay is still experimental. As such, expect things to break and change in the coming months. OneWay is a super simple library for state ma

SeungYeop Yeom 41 Dec 20, 2022
Reactive Keyboard in iOS

RxKeyboard RxKeyboard provides a reactive way of observing keyboard frame changes. Forget about keyboard notifications. It also perfectly works with U

RxSwift Community 1.4k Dec 29, 2022
A configurable api client based on Alamofire4 and RxSwift4 for iOS

SimpleApiClient A configurable api client based on Alamofire4 and RxSwift4 for iOS Requirements iOS 8.0+ Swift 4 Table of Contents Basic Usage Unwrap

Jay 67 Dec 7, 2020
Two-way data binding framework for iOS. Only one API to learn.

BindKit A simple to use two-way data binding framework for iOS. Only one API to learn. Supports Objective-C, Swift 5, Xcode 10.2, iOS 8 and above. Shi

Electric Bolt 13 May 25, 2022