fix: guard nativeId lookup for UIKit responders - #1551
Conversation
|
Hey @zxrl Which iOS 27 beta did you test? |
|
This is the video from iOS 27.0-beta.0, no crash so far: Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-07-15.at.13.25.43.mov |
| #if KEYBOARD_CONTROLLER_NEW_ARCH_ENABLED | ||
| func testNativeIDReturnsNilForUIKitSuperviewWithoutNativeID() { | ||
| let superview = UIView() | ||
| let textField = UITextField() | ||
| superview.addSubview(textField) | ||
|
|
||
| let responder: UIResponder? = textField | ||
|
|
||
| XCTAssertNil(responder.nativeID) | ||
| } | ||
|
|
||
| func testNativeIDReadsReactSuperviewNativeID() { | ||
| let superview = ReactSuperview() | ||
| let textField = UITextField() | ||
| superview.nativeId = "react-view" | ||
| superview.addSubview(textField) | ||
|
|
||
| let responder: UIResponder? = textField | ||
|
|
||
| XCTAssertEqual(responder.nativeID, "react-view") | ||
| } | ||
| #endif |
There was a problem hiding this comment.
These tests are testing mock implementation?
I don't think it makes a lot of sense to do that?
There was a problem hiding this comment.
They exercise the actual Optional<UIResponder>.nativeID implementation from UIResponder.swift, which is compiled directly into the native test target. ReactSuperview is only a fixture that exposes the selector.
You're right that the test target supplies a safeValue stub because this standalone project does not currently link the production Objective-C SafeKVC helper. So these tests specifically cover the new guard:
- a plain UIKit
UIViewreturnsnilbeforesafeValueis called; - a view exposing
nativeIdpasses the guard and is still read.
They do not cover the production NSObject+SafeKVC bridge itself. I can instead wire NSObject.swift and the Objective-C category into the native test target if you would prefer full production-path coverage over this isolated guard coverage.
|
Thanks — the crash was on a physical iPhone 15 Pro running iOS 27 beta 3 ( The symbolicated It terminates with Your recording is from a simulator, so the physical-device/toolchain combination may be the relevant difference. Could you confirm the simulator's exact iOS build number and Xcode version? I can also provide a sanitized copy of the crash report if useful. |
📜 Description
Restore the
nativeIdselector check before reading the property from a focused input's superview on iOS New Architecture.UIKit-owned inputs, including the text field created by
Alert.prompt, can become the current responder whileKeyboardProvideris mounted. Their superviews do not expose React Native'snativeIdproperty and must returnnilinstead of entering KVC.This also adds native regression coverage for both sides of the lookup:
nativeIdreturnsnil;nativeIdstill returns its value.💡 Motivation and Context
On iOS 27 beta, opening a React Native
Alert.promptwhileKeyboardProvideris active aborts as the keyboard appears. The relevant crash path is:The same class of crash was reported in #784 and fixed by #785 with a
responds(to:)check. #1174 later replaced that check with exception-based safe KVC. The exception-based path does not contain this UIKitnativeIdlookup on iOS 27, so this change restores the explicit capability check fornativeIdwhile retainingsafeValue(forKey:)for the actual read.I checked the current
mainbranch, release1.22.1, and open PR #1524; all still contain the unchecked lookup. I also searched open and closed issues and pull requests fornativeId,valueForUndefinedKey,Alert.prompt,UIAlertController,KeyboardAreaExtender,safeValue,NSUnknownKeyException, and iOS 27. I did not find an existing fix for this regression.Reproduction
KeyboardProviderin a New Architecture React Native app.Alert.prompt(...)on iOS.nativeIdlookup.Observed with react-native-keyboard-controller 1.22.0, React Native 0.86.0, Expo 57, and an iPhone 15 Pro running iOS 27.0 beta. The affected lookup is unchanged in 1.22.1.
📢 Changelog
iOS
nativeIdproperty;🤔 How Has This Been Tested?
xcodebuild build-for-testing -scheme KeyboardControllerNative -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO -quietAlert.promptremains open and stable with the keyboard visible;📝 Checklist