I've seen many different answers over time to how multiple CBCentralManager instances in one app behave.
In older versions of the iOS documentation, it was explicitly documented as not supported. That warning is no longer present.
My questions:
- what's the current iOS 9 behavior?
- what have the behaviors been over time in previous iOS versions?
- has Apple or an Apple employee backed up those answers?
Technically you can have more than one CBCentralManager instance in a single app.
If you end up having multiples due to some 3rd party library creating their own, just the existence of them will be OK besides the resource cost of each instance.
Outside the obvious resource hits (memory, CPU to process BLE events, etc.), it will also increase the messaging queue activity. These hits are low, but not negligible. So in the end, how many, and what do they do are the key questions.
What makes this a difficult question to answer is, while it is OK to design an app to use multiple managers without bad side effects and works efficiently, unfortunately that is frequently not the case. Through bad code or willful abuse there will be an app that creates hundreds of instances repeatedly doing one thing or another and will cripple BLE operations, and even worse crash the stack. I've seen this happen.
The important question becomes why do you need to do this. For example if your app is communicating with more than one type of peripheral at the same time - say, a heart monitor, a lost-keys tag, and say a thermostat - it would be an OK coding practice to create 3 separate delegate classes with their own managers; because each delegate would be handling each device completely differently.
Think how you create different ViewControllers for different types of views.
On the other end of the spectrum, if you are communicating with multiple peripherals of the same type, it is not a good practice to create a manager for each peripheral. This will not gain you anything, but each instance will have a resource cost as I explained above.
To refer you to the paragraph you quoted: "When your app implements the central role and adds support for state preservation and restoration, the system saves the state of your central manager object when the system is about to terminate your app to free up memory (if your app has multiple central managers, you can choose which ones you want the system to keep track of)."
Even outside of CoreBluetooth, it is always better to be a smaller target when the system comes knocking to free up memory. So, my personal suggestion would be to only use as many objects in your app as necessary.
To answer your specific questions:
- does altering the state on one (e.g. starting a scan) alter the state on another? Simple answer, if and only if not all of the managers are interacting with the same peripheral, is NO. They are independent. But if they are interacting with the same peripheral, the effects will depend on what is going on. If one manager is scanning, but the second one decides to connect, then the advertising will stop and the first manager will not discover the device. And so on...
- can CBPeripheral instances be shared between CBCentralManager instances? You can share the property data. If you are asking about the CBPeripheral object, you cannot. When a central manager connects to a peripheral, there will be a message link created, and any events from the peripheral will be routed to that particular central. Central managers can create their own instances of CPBeripheral for the same peripheral, and if both need to receive the same events (read above and decide whether this is necessary or a good idea), they will need to connect individually.
- can NSUUIDs of peripherals be shared between CBCentralManager instances? While this may work in some cases, there will be conditions that it will not. The UUID of peripherals can change and is assumed only temporary identifiers. Technically, two centrals can discover the same peripheral with different UUIDs
- is there any harm to having a series of short-lived CBCentralManager instances existing along side a long-lived instance? I would first ask, what is the point? I will refer you to my opening paragraphs again. Maybe the question you shoudl ask is "what is the benefit?"
- ... and for all of these questions, did iOS always behave this way? If not, what was first iOS version that did? Unfortunately I cannot answer this question. A lot has changed with CoreBluetooth between iOS 7 and iOS 9, including a lot of fixes that changed behaviour. Best would be to test your app against these versions and determine if the behaviour suits your use case.
From your description of what you are trying to accomplish, it sounds like you are trying to solve a code architecture issue, and do not necessarily need multiple Central Managers. You can create a singleton class that handles CoreBluetooth with a single manager, which then would dispatch different events (scanning, connecting, etc.) to the appropriate handler classes.