iOS swift BLE updateValue() without PeripheralManagerIsReady

I want to fully control the BLE send timing myself, instead of relying on the iOS system.

When I try to send a large data block using BLE (i.e., splitting it and sending multiple times), I follow Apple’s official guide. However, after the first successful updateValue() call in my loop, the second call always fails unless I wait for the peripheralManagerIsReady(toUpdateSubscribers:) callback. This callback timing is managed by the system, so I can’t control exactly when I can send the next packet.

If I send data manually by clicking a button, updateValue() always returns true—even if I add a long delay (like sleep(10)) between calls. But in a loop, after the first send, updateValue() returns false until the thread leaves or the callback occurs. I suspect this is a thread or queue issue blocking subsequent sends.

I also tried using DispatchQueue.global().async {} in the loop, but the result is the same.

Is there any way to fully control when I call updateValue(), without waiting for peripheralManagerIsReady()? Or is this a limitation of iOS BLE?

Thank you!

When you call updateValue() the data you are sending is added to a transmit queue. While making a function call is relatively instantaneous, physically sending data through a BLE connection takes time. Because of this CoreBluetooth has added the peripheralManagerIsReady() callback to let you know the data pipeline from your app, through the Bluetooth stack and the hardware layer is now available to be sent more data.

The usage pattern is as follows:

  1. call updateValue()
  2. if it returns true, back to 1
  3. if it returns false, wait for peripheralManagerIsReady()
  4. back to 1

If your data blocks are large, that could be why a single write is filling the transmit queue.

If you are looking for a better bandwidth there are other techniques you can try, like a larger MTU size, BLE EDL packets, and so on. These will need to be managed by the accessory you are connecting to as CoreBluetooth does not provide any APIs to do so.


Argun Tekant /  DTS Engineer / Core Technologies

iOS swift BLE updateValue() without PeripheralManagerIsReady
 
 
Q