Behavior differences when using CBCentralManager on different iPhone configurations

Hi,

I am developing an app that checks if Bluetooth is available on the device or not (does not actually use any Bluetooth capabilities). The only CoreBluetooth API's that I use are:

  • CBCentralManager
  • the state property of the CBCentralManager
  • centralManagerDidUpdateState

When I am testing, I experience different behaviors on my test devices. On an iPhone 15 iOS 18.5, the app works fine. However, on an iPhone 13 iOS 18.3.2, the app crashes with the following error:

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSBluetoothAlwaysUsageDescription key with a string value explaining to the user how the app uses this data.

Why is this permission required on my iPhone 13 iOS 18.3.2, but not my iPhone 15 iOS 18.5? Why do I experience different behavior on different iPhone configurations?

The only explanation I can think of is that the build configurations for the two builds you are testing on each is not the same, and you are somehow missing (or somehow including) the privacy string in one of them.

Your app will crash regardless of the phone model on iOS 18, the moment you instantiate a CBCentralManager if it does not have the privacy string declared.

So it looks like the difference in behavior is due to the difference in iOS version.

Before you assume that, change the bundle ID of the app your testing and retest on the iPhone 15/iOS 18.5 device (the one that doesn't crash). I suspect you'll find that it will also start crashing.

What's happening here is that at some point in the past you ran and authorized a build that DID include the required permission string. The system saved that authorization choice on the device, which then avoids the crash (because the system doesn't look for the plist key if the user has already authorized it).

In theory deleting and reinstalling the app should reset these choices, however, that behavior can also be inconsistent across iOS version and the exact install/reinstall process. Similarly, the App Store/Test Flight install process tends to be MUCH better at reseting this kind of data than Xcode*.

*This is largely intentional. By design, Xcode uses a somewhat different install process which is designed for speed and to minimize disruptions to the larger system.

One thing to keep in mind here is that if this WAS an iOS version/device issue (which I don't think it is), then what would be an extremely serious privacy/security bug. These dialogs exist for a reason and aren't something that would "disappear" between system versions.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hi Kevin, thank you for your thorough answer. I changed the bundle ID of my app that I am testing and retested on the iPhone 15 iOS 18.5 and it still did not crash. I went ahead and also tested the app (with the new bundle ID) on the iPhone 15 iOS 18.3.2 and it crashed. Please advise for next steps, thank you!

Please file a bug on this immediately and then post the bug number back here. After investigating this further, I think this may have been caused by the fix we applied for a different issue (r.146393304) in iOS 18.5. That's already being investigated in iOS 26, but I want to make sure we've got a developer bug tracking this on iOS 18.x.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Behavior differences when using CBCentralManager on different iPhone configurations
 
 
Q