From e42b444277e8cdb4e3320888cb33e143845d218c Mon Sep 17 00:00:00 2001 From: Dhruv317 Date: Tue, 24 Mar 2026 23:59:02 -0700 Subject: [PATCH] fix(ios): ensure contentView forwards touches after glass effect setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When UIGlassEffect is applied to a UIVisualEffectView, the internal contentView (_UIVisualEffectContentView) can be reconfigured with userInteractionEnabled = false if no subviews are present at the time the effect is set. In React Native's Fabric renderer, child component views are mounted into contentView via mountChildComponentView: — but this can happen *after* layoutSubviews triggers setupView() and applies the glass effect. The result is that contentView's touch handling is locked in a "no children" state, and Pressable/Touchable children never receive touch events for the lifetime of that view. This is a race condition that depends on main thread scheduling between Fabric's mount pass and UIKit's layout pass. It manifests as an intermittent, session-level bug: either all LiquidGlassView instances in a Fabric commit get working touch, or none of them do. The fix: explicitly set contentView.isUserInteractionEnabled = true after every effect application, guaranteeing touches always flow through to child views regardless of mount ordering. Co-Authored-By: Claude Opus 4.6 (1M context) --- ios/LiquidGlassView.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ios/LiquidGlassView.swift b/ios/LiquidGlassView.swift index 1be2f0b..f1066a9 100644 --- a/ios/LiquidGlassView.swift +++ b/ios/LiquidGlassView.swift @@ -75,6 +75,14 @@ import UIKit // Animate only the effect is changed after first mount. UIView.animate { self.effect = glassEffect } } + + // UIGlassEffect can reconfigure the internal contentView in a way that + // disables user interaction when no subviews are present at the time the + // effect is applied. In React Native (Fabric), child component views may + // be mounted into contentView *after* layoutSubviews triggers setupView(), + // leaving contentView with userInteractionEnabled == false for the + // lifetime of this view. Force it back on so touches always reach children. + self.contentView.isUserInteractionEnabled = true } }