2

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?

Caleb Kleveter
  • 11,170
  • 8
  • 62
  • 92

2 Answers2

5

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)

}
Caleb Kleveter
  • 11,170
  • 8
  • 62
  • 92
  • 6
    You need to keep references to the CBPeripheral else, they will be released. It's not about the "delegate to sell", but more about `self.remotePeripheral.append(peripheral)`. – Larme Oct 18 '16 at 16:35
  • I'll add that's it's a little more explained there: http://stackoverflow.com/questions/26377470/ios-corebluetooth-centralmanagerdidconnectperipheral-didfailtoconnectperiph (it's in Objective-C, but the situation is the same: CoreBluetooth doesn't keep strong references on the parameters, so they may be released too soon) – Larme Oct 21 '16 at 08:51
  • Saved me after 8 hours of debugging, searching on SO + trial & error! Thanks – Patrick Samy Aug 01 '18 at 14:58
1

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

Dharman
  • 30,962
  • 25
  • 85
  • 135
Siddharth Choudhary
  • 1,069
  • 1
  • 15
  • 20