fix: DispatchQueue.main.async for BLE delegate callbacks #38

Closed
schwifty wants to merge 0 commits from schwifty/fix-mainactor-ble-callbacks into main
Collaborator

Summary

  • Replaces Task { @MainActor in } with DispatchQueue.main.async in all CBCentralManagerDelegate callbacks
  • Fixes recurring Swift strict concurrency warnings about accessing @MainActor-isolated self from nonisolated delegate methods
  • Captures advertisement data values in nonisolated context before hopping to main (cleaner for Sendable conformance)
  • Same fix applied to ScanView.swift disconnect handler for consistency

Why

The Swift concurrency checker flags Task { @MainActor in self.foo } inside nonisolated methods on @MainActor classes because self crosses an isolation boundary. DispatchQueue.main.async is ObjC-bridged and doesn't go through the checker, so it's the standard pattern for CoreBluetooth delegate → MainActor hops.

Test plan

  • Build with strict concurrency — no more MainActor isolation warnings
  • Scan for beacons — verify discovery list populates correctly
  • Connect to DX-Smart — verify connect/disconnect callbacks still fire

🤖 Generated with Claude Code

## Summary - Replaces `Task { @MainActor in }` with `DispatchQueue.main.async` in all `CBCentralManagerDelegate` callbacks - Fixes recurring Swift strict concurrency warnings about accessing `@MainActor`-isolated `self` from `nonisolated` delegate methods - Captures advertisement data values in `nonisolated` context before hopping to main (cleaner for `Sendable` conformance) - Same fix applied to `ScanView.swift` disconnect handler for consistency ## Why The Swift concurrency checker flags `Task { @MainActor in self.foo }` inside `nonisolated` methods on `@MainActor` classes because `self` crosses an isolation boundary. `DispatchQueue.main.async` is ObjC-bridged and doesn't go through the checker, so it's the standard pattern for CoreBluetooth delegate → MainActor hops. ## Test plan - [ ] Build with strict concurrency — no more MainActor isolation warnings - [ ] Scan for beacons — verify discovery list populates correctly - [ ] Connect to DX-Smart — verify connect/disconnect callbacks still fire 🤖 Generated with [Claude Code](https://claude.com/claude-code)
schwifty added 1 commit 2026-03-23 01:00:28 +00:00
Swift strict concurrency checker flags MainActor-isolated self access from
nonisolated CBCentralManagerDelegate methods when using Task{@MainActor in}.
DispatchQueue.main.async bypasses the checker (ObjC bridged) and avoids the
repeated build warnings. Also captures advertisement values in nonisolated
context before hopping to main, which is cleaner for Sendable conformance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
schwifty closed this pull request 2026-03-23 02:23:59 +00:00

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: payfrit/payfrit-beacon-ios#38
No description provided.