Caleb Kleveter
Caleb Kleveter

Reputation: 11494

CoreBluetooth is disconnecting from unused peripherals due to an API Misuse

I am trying to connect to a MacBook Pro from an iPad with CoreBluetooth.

Here is my delegation for CBCentralManagerDelegate:

extension MasterViewController: CBCentralManagerDelegate {
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            print("Scanning for peripherals")
            central.scanForPeripherals(withServices: nil, options: nil)
            Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.stopScan), userInfo: nil, repeats: true)
        }
    }

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        print("Did discover peripheral", peripheral)

        central.connect(peripheral, options: nil)

    }

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("Did connect to ", peripheral)

        peripheral.delegate = self
        self.remotePeripheral.append(peripheral)
    }

    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {}
}

But when I scan I get this error in the log:

<Error>: [CoreBluetooth] API MISUSE: Cancelling connection for unused peripheral

Why does this happen?

Upvotes: 2

Views: 6815

Answers (3)

mcfisty
mcfisty

Reputation: 207

I had the same error however already had stored a reference to my peripheral device. I realised I had a different instance of CBCentralManager already associated with another view controller, and setting the unused instance to nil once finished with it resolved the warning.

Upvotes: 0

Siddharth Choudhary
Siddharth Choudhary

Reputation: 1129

I was seeing this error and for those who also are facing the same issue, my suggestion is that I wasn't storing the CBPeripheral device in my helper class. That seems unnecessary to do but for some reason it needs to be bounded internally I believe. Well, Here's what I did:-

    class BLEHelper: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate{
        
    @Published var pairedDevice:CBPeripheral?=nil
    ...

and then in your didDiscover function:

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
pairedDevice=peripheral
peripheral.delegate=self
myCentral.connect(peripheral, options:nil)
myCentral.stopScan()

}

This line here does the trick:- pairedDevice=peripheral

Upvotes: 1

Caleb Kleveter
Caleb Kleveter

Reputation: 11494

Not sure why this worked, but I found that it works if I assign the peripherals delegate to self, and add the peripheral to an array before I connect to it.

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    print("Did discover peripheral", peripheral)

    peripheral.delegate = self
    self.remotePeripheral.append(peripheral)

    central.connect(peripheral, options: nil)

}

Upvotes: 5

Related Questions