Skip to content

fix: Avoid recursive view loading - #8941

Merged
philprime merged 3 commits into
mainfrom
fix/avoid-recursive-view-loading
Sep 7, 2026
Merged

fix: Avoid recursive view loading#8941
philprime merged 3 commits into
mainfrom
fix/avoid-recursive-view-loading

Conversation

@philprime

Copy link
Copy Markdown
Member

📜 Description

Prevent relevant view controller traversal from loading views while checking whether a child container fills its parent. The traversal now uses viewIfLoaded for both controllers instead of reading childVC.view and topVC.view.

This keeps Sentry's tracing instrumentation from recursively entering an unloaded parent view controller's loadView and invoking viewDidLoad twice.

💡 Motivation and Context

A reported production crash showed a view controller executing viewDidLoad twice while Sentry tracing was enabled. The second invocation caused FluentUI to register the same token observer twice and fail with Attempting to double-register for tokenSet updates!.

This is a variant of #3753. That fix guarded only childVC.isViewLoaded. When the child navigation controller was already loaded but its parent was not, comparing its frame against topVC.view.bounds still loaded the parent recursively during Sentry's swizzled loadView path.

The regression test recreates that hierarchy with an unloaded parent and a loaded child navigation controller. Before the fix, it observed two viewDidLoad invocations. With the fix, it observes one.

💚 How did you test it?

  • Confirmed the new reproducer failed before the fix because viewDidLoad ran twice instead of once.
  • Confirmed the reproducer passed after the fix.
  • Ran all 47 SentryUIViewControllerSwizzlingTests successfully.
  • Ran make format.
  • Ran make analyze successfully.
  • Ran make build-ios FOR_AGENTS=true successfully.

📝 Checklist

You have to check all boxes before merging:

  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.
  • If I added a new public API, I also added it to the SentryObjC wrapper.

Use viewIfLoaded while identifying full-screen container children so relevant view controller traversal cannot re-enter a parent's loadView.

Cover the swizzled tracing path with a regression test that verifies viewDidLoad runs once when a loaded navigation child belongs to an unloaded parent.
@philprime philprime self-assigned this Sep 3, 2026
@philprime philprime added the run-full-ci Allows gated GitHub Action workflows to run for a labelled pull request label Sep 3, 2026
@philprime
philprime marked this pull request as ready for review September 3, 2026 15:22
@sentry

sentry Bot commented Sep 3, 2026

Copy link
Copy Markdown

📲 Install Builds

iOS

🔗 App Name App ID Version Configuration
SDK-Size io.sentry.sample.SDK-Size 9.27.0 (1) Release

⚙️ sentry-cocoa Build Distribution Settings

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1227.59 ms 1271.92 ms 44.33 ms
Size 24.14 KiB 1.32 MiB 1.29 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
d244305 1217.61 ms 1249.51 ms 31.90 ms
b524775 1220.17 ms 1244.51 ms 24.34 ms
c34c99b 1220.10 ms 1259.33 ms 39.22 ms
bbb8fdc 1227.79 ms 1258.28 ms 30.49 ms
4d32b0c 1216.38 ms 1255.98 ms 39.60 ms
96e2288 1205.88 ms 1234.78 ms 28.90 ms
b5f0d9a 1227.05 ms 1254.18 ms 27.13 ms
89c6f79 1215.43 ms 1256.32 ms 40.89 ms
fc4e913 1221.61 ms 1253.82 ms 32.21 ms
809b6b3 1222.13 ms 1264.55 ms 42.43 ms

App size

Revision Plain With Sentry Diff
d244305 24.14 KiB 1.30 MiB 1.28 MiB
b524775 24.14 KiB 1.24 MiB 1.21 MiB
c34c99b 24.14 KiB 1.29 MiB 1.27 MiB
bbb8fdc 24.14 KiB 1.17 MiB 1.14 MiB
4d32b0c 24.14 KiB 1.25 MiB 1.23 MiB
96e2288 24.14 KiB 1.31 MiB 1.29 MiB
b5f0d9a 24.14 KiB 1.24 MiB 1.21 MiB
89c6f79 24.14 KiB 1.29 MiB 1.27 MiB
fc4e913 24.14 KiB 1.17 MiB 1.15 MiB
809b6b3 24.14 KiB 1.31 MiB 1.29 MiB

Previous results on branch: fix/avoid-recursive-view-loading

Startup times

Revision Plain With Sentry Diff
f260cc8 1237.31 ms 1269.76 ms 32.44 ms
bc107f6 1228.62 ms 1255.52 ms 26.90 ms

App size

Revision Plain With Sentry Diff
f260cc8 24.14 KiB 1.32 MiB 1.29 MiB
bc107f6 24.14 KiB 1.32 MiB 1.29 MiB

@philprime
philprime enabled auto-merge (squash) September 4, 2026 08:26
@philprime
philprime merged commit f253129 into main Sep 7, 2026
260 of 265 checks passed
@philprime
philprime deleted the fix/avoid-recursive-view-loading branch September 7, 2026 07:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved run-full-ci Allows gated GitHub Action workflows to run for a labelled pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants