Commit 31371bf
committed
fix(ios): prevent RCTGenericDelegateSplitter crash when UIKit invokes selector on empty delegates
Summary
=======
RCTGenericDelegateSplitter stores delegates in an NSHashTable weakObjectsHashTable.
When the splitter is installed as UIScrollView.delegate, UIKit caches which
optional selectors the delegate responds to. If iOS later deallocates the
underlying delegate objects under memory pressure while the app is suspended,
the weak hash table silently drops the references. The splitter itself is still
retained by UIScrollView.
When the app returns to foreground, UIAnimator resumes an in-flight
UIScrollViewScrollAnimation left over from setContentOffset:animated:YES. UIKit
calls into the cached delegate (the splitter) and the Objective-C runtime asks
for a method signature via methodSignatureForSelector:, which returns nil because
_delegates is now empty. The runtime then invokes doesNotRecognizeSelector: and
raises NSInvalidArgumentException.
Fix
===
Fall back to a valid NSMethodSignature when no delegate handles the selector, so
forwardInvocation: can safely no-op instead of raising. The signature is resolved
from UIScrollViewDelegate's protocol method descriptions (all methods on that
protocol are optional), with a permissive v@:@ signature as a last resort.
Impact
======
Observed in a production RN 0.82.1 app: 273 fatal occurrences / 128 affected
users over ~3 months, across iOS 17.6 - 26.3.1 and iPhone 13 - 17 Pro. Strongly
correlated with low free_memory (<400MB) and long background suspension.
Related
=======
Commit e7ef992 addressed a closely related
dealloc-ordering crash by setting _scrollView.delegate = nil on dealloc. That
fix does not cover the foreground-resume path described here, because the
splitter survives but its weak delegates do not.1 parent 3982315 commit 31371bf
1 file changed
Lines changed: 13 additions & 1 deletion
Lines changed: 13 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
| |||
73 | 75 | | |
74 | 76 | | |
75 | 77 | | |
76 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
77 | 89 | | |
78 | 90 | | |
79 | 91 | | |
| |||
0 commit comments