Skip to content

fix(status-bar): avoid retain cycle between StatusBar and the bridge#2569

Open
puneet25 wants to merge 1 commit into
ionic-team:mainfrom
puneet25:fix/status-bar-bridge-retain-cycle
Open

fix(status-bar): avoid retain cycle between StatusBar and the bridge#2569
puneet25 wants to merge 1 commit into
ionic-team:mainfrom
puneet25:fix/status-bar-bridge-retain-cycle

Conversation

@puneet25

Copy link
Copy Markdown

What

Makes StatusBar.bridge a weak reference and updates its call sites to use optional chaining.

Why

StatusBar holds a strong reference to the bridge, while the bridge transitively owns the StatusBar instance:

CapacitorBridge → plugins → StatusBarPlugin → statusBar: StatusBar → bridge (strong)

This is a retain cycle, so a CapacitorBridge that registers the StatusBar plugin can never be deallocated, and neither can any of its registered plugins. In apps that create and destroy bridges over their lifetime (for example multiple CAPBridgeViewControllers, or Ionic Portals apps that create a PortalUIView per embedded web view), every discarded bridge leaks its full plugin set and the associated WebKit resources. Memory grows without bound with each create/destroy cycle.

Reproduction

  1. Create and present a CAPBridgeViewController (or PortalUIView) with the StatusBar plugin registered.
  2. Dismiss it and drop all references.
  3. Capture an Xcode Memory Graph: the CapacitorBridge, StatusBarPlugin, and all other registered CAPPlugin instances remain alive. The graph shows the cycle above.

With this change, the same flow releases the bridge and all plugins; instance counts return to baseline after each cycle (verified with Xcode Memory Graph before/after).

Notes

  • weak back references to the bridge are the established pattern elsewhere, e.g. CAPPlugin.bridge and WebViewDelegationHandler.bridge in Capacitor core.
  • Behavior is unchanged while the bridge is alive. The bridge outlives StatusBar in normal operation (it owns it), so the optional paths only take effect during teardown, where the previous code would have kept the object graph alive instead.

@puneet25
puneet25 force-pushed the fix/status-bar-bridge-retain-cycle branch from 683f915 to 57c0270 Compare July 22, 2026 15:34
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.

1 participant