Skip to content

Improve iPhone↔Mac connection reliability#1

Merged
donny-son merged 2 commits into
mainfrom
claude/determined-johnson-shorv9
Jun 22, 2026
Merged

Improve iPhone↔Mac connection reliability#1
donny-son merged 2 commits into
mainfrom
claude/determined-johnson-shorv9

Conversation

@donny-son

Copy link
Copy Markdown
Contributor

Why

The MultipeerConnectivity link between the iPhone and Mac was unstable — commands occasionally dropped and reconnects were unreliable. Reviewing both connection managers surfaced several concrete causes.

What changed

1. Mac recreates its session on disconnect (biggest fix)
Previously the iPhone recreated its MCSession on every drop but the Mac reused its old one for the next invitation. After a drop that session can be left half-dead, so the next connection was flaky. The Mac now recreates a clean session on full disconnect, mirroring the iPhone.

2. Bidirectional keepalive + stale-link watchdog
The keepalive was fire-and-forget (iPhone → Mac, no reply), so neither side could tell a "connected" session had actually gone dead. Now:

  • The Mac replies to each keepalive with a keepaliveAck.
  • Both sides track the time of the last inbound packet and, if nothing arrives for ~9s (≈3 missed keepalives), tear down and cleanly reconnect.

This catches half-open links that MCSession still reports as .connected — the usual cause of silently-dropped slide commands.

3. Duplicate-invitation guard
The reconnect timer and browser(foundPeer:) could both invite the same Mac at once, which makes MultipeerConnectivity bounce the connection. Invitations are now guarded by an in-flight flag.

4. Persistent MCPeerID
Both apps created a fresh MCPeerID each launch. Apple recommends reusing one — a new ID with the same display name is treated as a different peer, causing phantom/duplicate peers and confusing reconnection-by-name. It's now archived to UserDefaults and reused.

5. Reconnect backoff + faster invite timeout
Fixed 1s retry replaced with exponential backoff + jitter (1→2→4→8s capped). Invite timeout shortened 30s → 15s so a stuck invitation no longer blocks reconnection for half a minute.

Notes

  • The persistent-peer helper is wrapped in #if canImport(MultipeerConnectivity) because Shared/ also compiles into the watchOS target, where the framework isn't available.
  • No exhaustive switch over RemoteCommand exists outside the enum itself, which was updated for the new keepaliveAck case.

Testing

⚠️ Built and reviewed on Linux — not compiled against the iOS/macOS SDKs, which aren't available in this environment. Please build the DeckMac and DeckiOS schemes locally and verify a real iPhone↔Mac connect / drop / reconnect cycle before merging.

🤖 Generated with Claude Code


Generated by Claude Code

claude and others added 2 commits June 21, 2026 23:48
The MultipeerConnectivity link between the iPhone and Mac dropped commands
and reconnected unreliably. This addresses the main causes:

- Mac now recreates its MCSession on full disconnect (it previously reused a
  possibly half-dead session for the next invitation, while the iPhone always
  recreated its own — an asymmetry that caused flaky reconnects).
- Bidirectional keepalive + watchdog: the Mac now ACKs keepalives, and both
  sides tear down and cleanly reconnect when no traffic arrives for ~9s. This
  detects half-open links that MCSession still reports as `.connected`.
- Guard against overlapping invitations (the reconnect timer and
  browser(foundPeer:) could both invite the same Mac at once, bouncing the
  connection).
- Persist MCPeerID across launches (Apple's recommendation) to avoid
  phantom/duplicate peers and stabilize reconnection-by-name.
- Exponential backoff with jitter on reconnect instead of a fixed 1s retry;
  invite timeout shortened 30s → 15s for faster recovery.

The persistent-peer helper is guarded with `#if canImport(MultipeerConnectivity)`
since the Shared sources also compile into the watchOS target, where the
framework is unavailable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0111bgqmC4myR1hzdTBio4ri
@donny-son donny-son marked this pull request as ready for review June 22, 2026 17:58
@donny-son donny-son merged commit 78691ec into main Jun 22, 2026
3 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.

2 participants