Skip to content

fix(ios): stabilize blur intensity after mount with CADisplayLink#116

Merged
sbaiahmed1 merged 2 commits into
sbaiahmed1:mainfrom
kOOnzTe:fix/ios-blur-stabilization-display-link
Jul 10, 2026
Merged

fix(ios): stabilize blur intensity after mount with CADisplayLink#116
sbaiahmed1 merged 2 commits into
sbaiahmed1:mainfrom
kOOnzTe:fix/ios-blur-stabilization-display-link

Conversation

@kOOnzTe

@kOOnzTe kOOnzTe commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Stabilize BlurEffectView during the first frames after mount, window attach, and foreground return.

Problem

BlurEffectView relies on a paused UIViewPropertyAnimator to preserve custom blur intensity. In practice, UIKit can still invalidate that animator during the first few frames after:

  • initial mount
  • moving into a window
  • returning from background

When that happens, the blur may briefly render with the wrong material state or appear unblurred until a later rebuild.

Solution

This change adds a short, bounded CADisplayLink stabilization pass:

  • start a 3-frame rebuild window after blur updates and didMoveToWindow
  • stop immediately when the view leaves the window
  • clean up the display link in deinit

This keeps the existing animator-based intensity approach, but makes it more resilient during UIKit transition timing.

Why this is safe

  • the stabilization window is intentionally tiny at 3 visible frames
  • work only runs while the view is attached to a window
  • existing blur behavior is preserved after the stabilization pass finishes
  • cleanup is explicit both on window detach and deallocation

Testing

  • mounted a screen containing BlurEffectView and verified blur stays applied on first render
  • navigated in and out of the screen and verified no temporary unblurred flash
  • backgrounded and foregrounded the app and verified blur intensity is restored cleanly

UIKit can invalidate the paused blur animator during the first few transition frames after mount. Rebuild across a short bounded window so the correct material intensity is restored without a visible flash.

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

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

BlurEffectView adds a bounded CADisplayLink stabilization period that rebuilds the blur animator after blur updates and window transitions, stops when detached, and is invalidated during teardown.

Changes

Blur stabilization

Layer / File(s) Summary
Stabilization triggers
ios/Views/BlurEffectView.swift
Blur updates and window attachment rebuild the animator and start stabilization; window detachment stops it.
Display-link stabilization and cleanup
ios/Views/BlurEffectView.swift
Display-link ticks rebuild the animator for a bounded frame budget, with explicit invalidation during teardown.

Estimated code review effort: 3 (Moderate) | ~15–30 minutes

Possibly related PRs

Suggested reviewers: DanielAraldi

Sequence Diagram(s)

sequenceDiagram
  participant UIWindow
  participant BlurEffectView
  participant CADisplayLink
  UIWindow->>BlurEffectView: attach view
  BlurEffectView->>BlurEffectView: rebuildAnimator()
  BlurEffectView->>CADisplayLink: schedule stabilization
  CADisplayLink->>BlurEffectView: handleStabilizationTick()
  BlurEffectView->>BlurEffectView: rebuildAnimator()
  BlurEffectView->>CADisplayLink: invalidate after frame budget
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main iOS blur stabilization change and mentions the key implementation detail.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
ios/Views/BlurEffectView.swift (1)

86-101: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Break the CADisplayLink retain cycle
CADisplayLink(target: self, ...) keeps BlurEffectView alive through stabilizationDisplayLink, so deallocation can be delayed until the 3-frame window ends. A weak proxy would let deinit run immediately if the view is removed or the app backgrounds mid-stabilization.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ios/Views/BlurEffectView.swift` around lines 86 - 101, Break the
CADisplayLink retain cycle in startStabilizationIfNeeded by targeting a weak
proxy object instead of BlurEffectView directly; have the proxy forward
handleStabilizationTick to the view without retaining it, while preserving
existing stabilizationDisplayLink invalidation and callback behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@ios/Views/BlurEffectView.swift`:
- Around line 86-101: Break the CADisplayLink retain cycle in
startStabilizationIfNeeded by targeting a weak proxy object instead of
BlurEffectView directly; have the proxy forward handleStabilizationTick to the
view without retaining it, while preserving existing stabilizationDisplayLink
invalidation and callback behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5fd8cecb-8c4f-494e-9c72-2fd1a1087b0c

📥 Commits

Reviewing files that changed from the base of the PR and between 6df7e7f and 11b7b65.

📒 Files selected for processing (1)
  • ios/Views/BlurEffectView.swift

@omer-ayhan

Copy link
Copy Markdown

nice work🚀

@sbaiahmed1
sbaiahmed1 merged commit ea6f413 into sbaiahmed1:main Jul 10, 2026
@gorkemozkan

Copy link
Copy Markdown

Well done! @kOOnzTe

@sbaiahmed1

Copy link
Copy Markdown
Owner

Released in 4.7.1

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.

4 participants