[iOS 18] Initializing CBCentralManager doesn't trigger prompting Bluetooth permission sometimes

The issue

While testing how our app behaves on iOS 18 beta 6, we found an issue on one of our iPhones:

  • At some point, the app creates CBCentralManager in order to trigger an alert to request Bluetooth permission;
  • The alert is not shown;
  • centralManagerDidUpdateState never gets called, the state is always .unknown.

Below is a sample code I used to reproduce it easier:

class ViewController: UIViewController, CBCentralManagerDelegate {
    var centralManager: CBCentralManager?
    @IBOutlet weak var stateLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        print("Test app ready")
    }
    
    @IBAction func onPressedRequestPermission(_ sender: Any) {
        self.stateLabel.text = "Requested BLE permission"
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }
    
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        var stateString = ""
        switch central.state {
        case .poweredOn: stateString = "poweredOn"
        case .unknown: stateString = "unknown"
        case .resetting: stateString = "resetting"
        case .unsupported: stateString = "unsupported"
        case .unauthorized: stateString = "unauthorized"
        case .poweredOff: stateString = "poweredOff"
        @unknown default: stateString = "unknownDefault"
        }
        
        print("CBCentralState changed: \(stateString)")
        self.stateLabel.text = "CBCentralState: \(stateString)"
    }
}

I ran this code on two devices - one with the issue and one without it, and compared the logs from Console. I noticed that the last similar logs were

15:44:25.428118+0200	tccd	AUTHREQ_PROMPTING: msgID=8163.2, service=kTCCServiceBluetoothAlways, subject=Sub:{...

After that, the bug-free device printed this within the next ~250ms:

15:44:25.432285+0200	SpringBoard	Asked to bootstrap a new process for handle: [osservice<com.apple.tccd>:8144]
...
15:44:25.675380+0200	SpringBoard	Received request to activate alertItem: <SBUserNotificationAlert: 0xc4289cf00; title: Allow “test1” to find Bluetooth devices?; source: tccd; pid: 8144>

and showed the request for Bluetooth permission. At the same time, there were no such logs on the problematic device, and the request was not displayed.

Other apps behavior

nRF Connect app cannot request Bluetooth permission too on the same device. Usually it does that immediately after the first launch, but this time we saw only an error "Your device reports an unknown error for Bluetooth use." and no BT request alert.

The question

How can we programmatically detect that there is some unknown issue with Bluetooth in a similar way how nRF Connect does that?

Answered by synthezator in 803154022

I asked Nordic the same question - in their case they use CBCentralManagerState.unknown (and perhaps a few others) to display this message. So it looks like the only workaround to detect an error is to track whether the app gets inactive within some timeout after creating CBCentralManager. If it doesn't, it means that the permission wasn't requested by iOS.

Attaching a screenshot from nRF Connect:

Our engineering teams need to investigate this issue, as this might indicate an issue with iOS 18 Beta.

We'd greatly appreciate it if you could open a bug report, include crash logs and sample code or models that reproduce the issue, and post the FB number here once you do.

It would be very helpful if you could please go to https://developer.apple.com/bug-reporting/profiles-and-logs/ and follow the instructions for Bluetooth for iOS to install a debugging profile on your device. Then reproduce the issue, and follow the instructions at the above link to create a sysdiagnose. And attach that to the Feedback report as well.

Bug Reporting: How and Why? has tips on creating a successful bug report.


Argun Tekant /  DTS Engineer / Core Technologies

Unfortunately the issue has gone after our engineers reset network settings on the iPhone. I will report the issue when it appears again.

Anyway, we would like to at least display some warning to users in similar cases, like nRF Connect does it. At the moment our app receives no error nor CBCentralStatus update after creating CBCentralManager, and it doesn't allow users to proceed, so they get stuck without any warning.

Is there a way to detect unknown errors programmatically?

Accepted Answer

I asked Nordic the same question - in their case they use CBCentralManagerState.unknown (and perhaps a few others) to display this message. So it looks like the only workaround to detect an error is to track whether the app gets inactive within some timeout after creating CBCentralManager. If it doesn't, it means that the permission wasn't requested by iOS.

[iOS 18] Initializing CBCentralManager doesn't trigger prompting Bluetooth permission sometimes
 
 
Q