Skip to content

feat(ios): add CoreBluetooth state restoration#247

Merged
fotiDim merged 6 commits into
Navideck:mainfrom
delmoncompanysa-eng:ios-state-restoration
Jun 4, 2026
Merged

feat(ios): add CoreBluetooth state restoration#247
fotiDim merged 6 commits into
Navideck:mainfrom
delmoncompanysa-eng:ios-state-restoration

Conversation

@delmoncompanysa-eng

Copy link
Copy Markdown
Contributor

Opt the central manager into state preservation/restoration via CBCentralManagerOptionRestoreIdentifierKey and implement centralManager(_:willRestoreState:) so iOS can relaunch the app in the background when a managed peripheral reconnects and hand the live connection back. The manager is eagerly created at plugin registration (inside didFinishLaunchingWithOptions) so willRestoreState can fire.

Opt the central manager into state preservation/restoration via
CBCentralManagerOptionRestoreIdentifierKey and implement
centralManager(_:willRestoreState:) so iOS can relaunch the app in the
background when a managed peripheral reconnects and hand the live
connection back. The manager is eagerly created at plugin registration
(inside didFinishLaunchingWithOptions) so willRestoreState can fire.

Co-authored-by: Cursor <cursoragent@cursor.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements CoreBluetooth state preservation and restoration for iOS in the UniversalBlePlugin Swift code. It eagerly instantiates the central manager during plugin registration and configures it with a stable restoration identifier. It also implements the centralManager(_:willRestoreState:) delegate method to re-adopt restored peripherals. Feedback on these changes suggests removing the insertion of restored peripherals into autoConnectDevices because it may override the original auto-connect configuration, and notes that autoConnectDevices is currently an unused variable that should be cleaned up entirely.

Comment thread darwin/universal_ble/Sources/universal_ble/UniversalBlePlugin.swift Outdated
Address review feedback: CoreBluetooth restores every peripheral that had
an active/pending connection regardless of its autoConnect configuration,
so unconditionally inserting them into autoConnectDevices in
willRestoreState was incorrect (and had no effect, since the set is not
read for reconnection). Drop the insertion and clarify the comment.

Co-authored-by: Cursor <cursoragent@cursor.com>
@delmoncompanysa-eng

Copy link
Copy Markdown
Contributor Author

Thanks — good catch. Fixed in 81badf3: removed the unconditional autoConnectDevices.insert(...) in willRestoreState, since CoreBluetooth restores peripherals regardless of their autoConnect configuration and the set isn't read for reconnection. Auto-connect intent now stays solely what connect(autoConnect:) recorded. Fully removing the (pre-existing) unused autoConnectDevices set is outside this PR's scope, but happy to do it in a follow-up if you'd prefer.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds iOS CoreBluetooth state preservation/restoration support to the Darwin implementation so iOS can relaunch the app in the background and hand back restored CBPeripheral connections, by ensuring the CBCentralManager is created with a restoration identifier early during app launch.

Changes:

  • Opts the iOS CBCentralManager into state restoration via CBCentralManagerOptionRestoreIdentifierKey, and forces eager manager creation at plugin registration time.
  • Implements centralManager(_:willRestoreState:) to re-adopt restored peripherals (delegate + cache repopulation) and best-effort notify Dart if already connected.
  • Updates the example lockfile to reflect the plugin version bump and Dart SDK resolution floor.

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated no comments.

File Description
example/pubspec.lock Updates resolved plugin version and SDK resolution metadata for the example app.
darwin/universal_ble/Sources/universal_ble/UniversalBlePlugin.swift Adds iOS state restoration identifier/configuration, eager manager init on registration, and restoration callback handling to rehydrate peripherals.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@fotiDim

fotiDim commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

@delmoncompanysa-eng thanks for the PR. Overall looks good although it is a bit heavy on comments. Could you please slim them down and keep them only where necessary? I could also do it after merge.

@fotiDim

fotiDim commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

@delmoncompanysa-eng we should also update the readme and document the new behavior. Is there a plist entry required?

@delmoncompanysa-eng

Copy link
Copy Markdown
Contributor Author

Done — slimmed the state-restoration comments to keep only the "why", documented the new iOS background state restoration behavior in the README (Permissions → iOS / macOS), and added a CHANGELOG entry.

Regarding the plist: yes. The consuming app must declare the bluetooth-central background mode under UIBackgroundModes in its Info.plist; without it iOS won't relaunch the app for Bluetooth events and willRestoreState: won't fire. I've documented this in the README.

Comment thread README.md Outdated
Comment thread README.md Outdated
@fotiDim fotiDim merged commit 7890e22 into Navideck:main Jun 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants