[CoreBluetooth] API MISUSE: <CBCentralManager: 0x28156d480> can only accept this command while in the powered on state

Hi, Im new to Bluetooth development in iOS, I have a simple app that connects to a bluetooth device and allows you to send commands via bluetooth.

The app is working fine when I run the app or run UI tests however in my unit tests I'm getting this issue were the the bluetooth controller init() function who's responsibility is to assign a bluetooth central manager:

 public override init() {

        super.init()

        myCentral = CBCentralManager(delegate: self, queue: nil)

        myCentral.delegate = self

        print("state: ")

        print(myCentral.state)

    }

The 'centralManagerDidUpdateState(_ central: CBCentralManager)' callback should then be invoked but this is not getting called until the end of my tests which I can't understand why.

    public func centralManagerDidUpdateState(_ central: CBCentralManager) {

        if central.state == .poweredOn {

            isSwitchedOn = true

            print("Bluetooth powered on")

        }

        else {

            isSwitchedOn = false

            print("Bluetooth not powered on")

        }

    }

and due to the long delay in assigning a central device when I try to run a command in my tests eg. connect I get the error from the title '[CoreBluetooth] API MISUSE: <CBCentralManager: 0x28156d480> can only accept this command while in the powered on state'.

I know the central is assigned at the end of my tests because 'bluetooth powered on' is logged as the last thing in my tests.

I've even tried modifying the tests by adding a call to connect at the very end of the tests or sleep time to see if it was just a time issue but the centralManager callback is still not invoked until all the test code is executed

Thanks in advance for any help provided :)

@newToThis123, based on your description, it looks like you're writing XCTest and now XCUITests. CoreBluetooth is not implemented on simulator so you'll never see a switch to .poweredOn in that case. Otherwise, if you are running your tests on a device, the test process is not your application and the bluetooth permissions don't carry over, so I don't think you'll get .poweredOn there either.

You could attempt to rewrite your unit tests as XCUITests, and put appropriate state machine logic around your connect call to ensure .poweredOn state before sending the connect call.

If you want to stick with XCTests (unit tests), or write Bluetooth related tests that can run on simulator, I might suggest abstracting your code a little bit like how it is done in this video and think differently about what you are actually testing. Testing in Xcode

[CoreBluetooth] API MISUSE: &lt;CBCentralManager: 0x28156d480&gt; can only accept this command while in the powered on state
 
 
Q