So I currently got a bluetooth connection setup between a iPad and iPhone. I've created my testcode in the ViewController
and everything works fine. Now I moved it to 2 manager classes one for the CBCentralManager
and one for the CBPeripheralManager
above those to classes I made a BluetoothManager
which is a singleton class and holds some information regarding currently connected devices.
However when doing this I'm facing a problem it seems like the centralManager.connect()
call doesn't actually work. I debugged my entire code and after that line nothing seems to happen and I can't seem to figure out why this is or where I'm actually going wrong.
The CentralManager class
import Foundation
import CoreBluetooth
class CentralManager: NSObject {
private var centralManager: CBCentralManager!
var peripherals: [CBPeripheral] = []
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
}
}
// MARK: - CBCentralManager Delegate Methods
extension CentralManager: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
centralManager.scanForPeripherals(withServices: [BLEConstants.serviceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
default:
break
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if !peripherals.contains(peripheral) {
peripheral.delegate = self
peripherals.append(peripheral)
centralManager.connect(peripheral, options: nil)
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.discoverServices([BLEConstants.serviceUUID])
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
guard let peripheralIndex = peripherals.index(of: peripheral), BluetoothManager.shared.deviceCharacteristic[peripheral] != nil else { return }
peripherals.remove(at: peripheralIndex)
BluetoothManager.shared.deviceCharacteristic.removeValue(forKey: peripheral)
}
}
// MARK: - CBPeripheral Delegate Methods
extension CentralManager: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
for service in peripheral.services! {
if service.uuid == BLEConstants.serviceUUID {
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic in service.characteristics! {
let characteristic = characteristic as CBCharacteristic
if BluetoothManager.shared.deviceCharacteristic[peripheral] == nil {
BluetoothManager.shared.deviceCharacteristic[peripheral] = characteristic
}
}
}
func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]) {
}
}
The PeripheralManager class
class PeripheralManager: NSObject {
private var peripheralManager: CBPeripheralManager!
override init() {
super.init()
peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
}
}
// MARK: - Manage Methods
extension PeripheralManager {
func updateAdvertising() {
guard !peripheralManager.isAdvertising else { peripheralManager.stopAdvertising(); return }
let advertisingData: [String: Any] = [CBAdvertisementDataServiceUUIDsKey: BLEConstants.serviceUUID,
CBAdvertisementDataLocalNameKey: BLEConstants.bleAdvertisementKey]
peripheralManager.startAdvertising(advertisingData)
}
func initializeService() {
let service = CBMutableService(type: BLEConstants.serviceUUID, primary: true)
let characteristic = CBMutableCharacteristic(type: BLEConstants.charUUID, properties: BLEConstants.charProperties, value: nil, permissions: BLEConstants.charPermissions)
service.characteristics = [characteristic]
peripheralManager.add(service)
}
}
// MARK: - CBPeripheralManager Delegate Methods
extension PeripheralManager: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
initializeService()
updateAdvertising()
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
for request in requests {
if let value = request.value {
let messageText = String(data: value, encoding: String.Encoding.utf8)
print(messageText ?? "")
}
self.peripheralManager.respond(to: request, withResult: .success)
}
}
}
The BluetoothManager class
class BluetoothManager {
static let shared = BluetoothManager()
private var centralManager: CentralManager!
private var peripheralManager: PeripheralManager!
var deviceCharacteristic: [CBPeripheral: CBCharacteristic] = [:]
var connectedPeripherals: [CBPeripheral] { return centralManager.peripherals }
func setup() {
centralManager = CentralManager()
peripheralManager = PeripheralManager()
}
}
and then in my ViewController didLoad
I'm calling BluetoothManager.shared.setup()
Does anyone know why the devices don't seem to connect with eachother or maybe the delegate functions after that just don't get called?