diff --git a/Sources/SwiftBluetooth/CentralManager/CentralManagerDelegateWrapper.swift b/Sources/SwiftBluetooth/CentralManager/CentralManagerDelegateWrapper.swift index e18d294..fffc715 100644 --- a/Sources/SwiftBluetooth/CentralManager/CentralManagerDelegateWrapper.swift +++ b/Sources/SwiftBluetooth/CentralManager/CentralManagerDelegateWrapper.swift @@ -11,9 +11,11 @@ class CentralManagerDelegateWrapper: NSObject, CBCentralManagerDelegate { // MARK: - CBCentralManagerDelegate conformance func centralManagerDidUpdateState(_ central: CBCentralManager) { guard let parent = self.parent else { return } + + parent.delegate?.centralManagerDidUpdateState(parent) + parent.eventQueue.async { parent.eventSubscriptions.recieve(.stateUpdated(parent.state)) - parent.delegate?.centralManagerDidUpdateState(parent) } } @@ -21,10 +23,11 @@ class CentralManagerDelegateWrapper: NSObject, CBCentralManagerDelegate { guard let parent = parent else { return } let peripheral = parent.peripheral(peripheral) + parent.connectedPeripherals.insert(peripheral) + parent.delegate?.centralManager(parent, didConnect: peripheral) + parent.eventQueue.async { - parent.connectedPeripherals.insert(peripheral) parent.eventSubscriptions.recieve(.connected(peripheral)) - parent.delegate?.centralManager(parent, didConnect: peripheral) } } @@ -32,13 +35,13 @@ class CentralManagerDelegateWrapper: NSObject, CBCentralManagerDelegate { guard let parent = parent else { return } let peripheral = parent.peripheral(peripheral) + parent.connectedPeripherals.remove(peripheral) + parent.delegate?.centralManager(parent, didDisconnectPeripheral: peripheral, error: error) + parent.removePeripheral(peripheral.cbPeripheral) + parent.eventQueue.async { - parent.connectedPeripherals.remove(peripheral) parent.eventSubscriptions.recieve(.disconnected(peripheral, error)) peripheral.eventSubscriptions.recieve(.didDisconnect(error)) - parent.delegate?.centralManager(parent, didDisconnectPeripheral: peripheral, error: error) - - parent.removePeripheral(peripheral.cbPeripheral) } } @@ -46,9 +49,10 @@ class CentralManagerDelegateWrapper: NSObject, CBCentralManagerDelegate { guard let parent = parent else { return } let peripheral = parent.peripheral(peripheral) + parent.delegate?.centralManager(parent, didFailToConnect: peripheral, error: error) + parent.eventQueue.async { parent.eventSubscriptions.recieve(.failToConnect(peripheral, error)) - parent.delegate?.centralManager(parent, didFailToConnect: peripheral, error: error) } } @@ -57,18 +61,20 @@ class CentralManagerDelegateWrapper: NSObject, CBCentralManagerDelegate { let peripheral = parent.peripheral(peripheral) peripheral.discovery = .init(rssi: RSSI, advertisementData: advertisementData) + parent.delegate?.centralManager(parent, didDiscover: peripheral, advertisementData: advertisementData, rssi: RSSI) + parent.eventQueue.async { parent.eventSubscriptions.recieve(.discovered(peripheral, advertisementData, RSSI)) - parent.delegate?.centralManager(parent, didDiscover: peripheral, advertisementData: advertisementData, rssi: RSSI) } } func centralManager(_ central: CBCentralManager, willRestoreState dict: [String: Any]) { guard let parent = parent else { return } + parent.delegate?.centralManager(parent, willRestoreState: dict) + parent.eventQueue.async { parent.eventSubscriptions.recieve(.restoreState(dict)) - parent.delegate?.centralManager(parent, willRestoreState: dict) } } @@ -77,18 +83,14 @@ class CentralManagerDelegateWrapper: NSObject, CBCentralManagerDelegate { guard let parent = parent else { return } let peripheral = parent.peripheral(peripheral) - parent.eventQueue.async { - parent.delegate?.centralManager(parent, connectionEventDidOccur: event, for: peripheral) - } + parent.delegate?.centralManager(parent, connectionEventDidOccur: event, for: peripheral) } func centralManager(_ central: CBCentralManager, didUpdateANCSAuthorizationFor peripheral: CBPeripheral) { guard let parent = parent else { return } let peripheral = parent.peripheral(peripheral) - parent.eventQueue.async { - parent.delegate?.centralManager(parent, didUpdateANCSAuthorizationFor: peripheral) - } + parent.delegate?.centralManager(parent, didUpdateANCSAuthorizationFor: peripheral) } #endif } diff --git a/Tests/SwiftBluetoothTests/CentralPeripheralTestCase.swift b/Tests/SwiftBluetoothTests/CentralPeripheralTestCase.swift index 0542fa6..d00bb3d 100644 --- a/Tests/SwiftBluetoothTests/CentralPeripheralTestCase.swift +++ b/Tests/SwiftBluetoothTests/CentralPeripheralTestCase.swift @@ -2,11 +2,112 @@ import XCTest @testable import CoreBluetoothMock @testable import SwiftBluetoothMock +fileprivate final class CentralManagerDelegateThreadChecker: CentralManagerDelegate { + func centralManagerDidUpdateState(_ central: CentralManager) { + XCTAssert(Thread.isMainThread) + } + + func centralManager(_ central: CentralManager, didConnect peripheral: Peripheral) { + XCTAssert(Thread.isMainThread) + } + + func centralManager(_ central: CentralManager, didDisconnectPeripheral peripheral: Peripheral, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func centralManager(_ central: CentralManager, didFailToConnect peripheral: Peripheral, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func centralManager(_ central: CentralManager, connectionEventDidOccur event: CBConnectionEvent, for peripheral: Peripheral) { + XCTAssert(Thread.isMainThread) + } + + func centralManager(_ central: CentralManager, didDiscover peripheral: Peripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) { + XCTAssert(Thread.isMainThread) + } + + func centralManager(_ central: CentralManager, willRestoreState dict: [String: Any]) { + XCTAssert(Thread.isMainThread) + } + + func centralManager(_ central: CentralManager, didUpdateANCSAuthorizationFor peripheral: Peripheral) { + XCTAssert(Thread.isMainThread) + } +} + +fileprivate final class PeripheralDelegateThreadChecker: PeripheralDelegate { + func peripheral(_ peripheral: Peripheral, didDiscoverServices error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didDiscoverIncludedServicesFor service: CBService, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didReadRSSI RSSI: NSNumber, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didModifyServices services: [CBService]) { + XCTAssert(Thread.isMainThread) + } + + func peripheral(_ peripheral: Peripheral, didOpen channel: CBL2CAPChannel?, error: Error?) { + XCTAssert(Thread.isMainThread) + } + + func peripheralDidUpdateName(_ peripheral: Peripheral) { + XCTAssert(Thread.isMainThread) + } +} + class CentralPeripheralTestCase: XCTestCase { let connectionTimeout: TimeInterval = 2 - var central: CentralManager! - var peripheral: Peripheral! + private let centralDelegate = CentralManagerDelegateThreadChecker() + private let peripheralDelegate = PeripheralDelegateThreadChecker() + + var central: CentralManager! { + didSet { + guard let central else { return } + central.delegate = centralDelegate + } + } + var peripheral: Peripheral! { + didSet { + guard let peripheral else { return } + peripheral.delegate = peripheralDelegate + } + } override func setUp() { mockPeripheral.connectionDelegate?.reset()