iosswiftcore-bluetoothstate-restoration

CoreBluetooth and State Preservation & Restoration when peripheral needs special ACK


I'm working with a Bluetooth peripheral that after connecting to it there is a ACK back and forth before it actually can send me the data that I need.

The flow is like this:

  1. Discover the peripheral
  2. Connect to the peripheral
  3. Discover services and characteristics
  4. Listen for updates on a specific characteristic
  5. Peripheral sends a special message to this characteristic
  6. The app then sends an ACK to the peripheral
  7. The peripheral sends me the data needed by the app

I have implemented the needed logic in the protocol method for State Preservation and Restoration centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any])

Question 1:

When the app is in the background and iOS decides to take over the Bluetooth communication (for resource reasons), how will iOS manage to do steps 5, 6 and 7?

Because if it can't then the peripheral won't be able to send the data that the app needs in step 7.

Question 2:

In the docs I read that iOS might start your app for a few seconds. Will the viewDidLoad method of my root ViewController be executed in that case? That's where I instantiate the CBCentralManager


Some of the many online resources that I've found:

Core Bluetooth Background Processing for iOS Apps

Zero to BLE on iOS – Part Three


Solution

  • These two comments from Paulw11 helped me understand what was going on:

    No, that doesn’t happen. If you have a pending discovery, a pending “connect” or you have an active notify on a characteristic then iOS will relaunch your app so that it can handle the discovery, the connection or the notification. iOS can’t do this on your behalf; it doesn’t know what you want to do. – Paulw11


    Having your Bluetooth object attached to a view controller is a bad idea if you want to perform operations in the background. I suggest a singleton or an object owned by your app delegate – Paulw11


    First, I was under the wrong assumption that iOS will try to handle all bluetooth communication on behalf of my app when my app was in the background and iOS had to kill it. The reality is that iOS starts the app in background mode for a limited period of time so that you can run your restoration code.

    Finally, having the logic in the viewDidLoad of my ViewController was wrong. I have created a BluetoothManager class and I instantiated it in the application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool method of my AppDelegate