Skip to content

Commit a0e768b

Browse files
Saadnajmiclaude
andcommitted
fix: replace RCTUISecureTextField #include hack with proper subclass
The old RCTUISecureTextField.m used `#include "../RCTUITextField.mm"` to re-compile the entire implementation with RCT_SUBCLASS_SECURETEXTFIELD defined. This caused duplicate symbol errors in SPM builds because both files were compiled as separate translation units. Replace with a proper OOP subclass: RCTUISecureTextField now inherits from RCTUITextField and overrides only what differs (NSSecureTextFieldCell). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fd287ee commit a0e768b

File tree

8 files changed

+103
-34
lines changed

8 files changed

+103
-34
lines changed

packages/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#import <React/RCTBackedTextInputDelegateAdapter.h>
99
#import "RCTBackedTextInputViewProtocol.h" // [macOS
1010
#import "RCTBackedTextInputDelegate.h"
11-
#import "../RCTTextUIKit.h" // macOS]
11+
#import <React/RCTTextUIKit.h> // macOS]
1212

1313
#pragma mark - RCTBackedTextFieldDelegateAdapter (for UITextField)
1414

packages/react-native/Libraries/Text/TextInput/RCTBaseTextInputView.mm

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
#import <React/RCTTextAttributes.h>
2222
#import <React/RCTTextSelection.h>
2323
#import <React/RCTUITextView.h> // [macOS]
24-
#import "../RCTTextUIKit.h" // [macOS]
24+
#import <React/RCTTextUIKit.h> // [macOS]
2525
#import <React/RCTHandledKey.h> // [macOS]
26+
#if TARGET_OS_OSX // [macOS
27+
#import <React/RCTUISecureTextField.h>
28+
#endif // macOS]
2629

2730
/** Native iOS text field bottom keyboard offset amount */
2831
static const CGFloat kSingleLineKeyboardBottomOffset = 15.0;
@@ -194,7 +197,7 @@ - (BOOL)textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldTex
194197
BOOL shouldFallbackToBareTextComparison =
195198
// There are multiple Korean input sources (2-Set, 3-Set, etc). Check substring instead instead
196199
[[[self.backedTextInputView inputContext] selectedKeyboardInputSource] containsString:@"com.apple.inputmethod.Korean"] ||
197-
[self.backedTextInputView hasMarkedText] || [self.backedTextInputView isKindOfClass:[NSSecureTextField class]] ||
200+
[self.backedTextInputView hasMarkedText] || [self.backedTextInputView isKindOfClass:[RCTUISecureTextField class]] ||
198201
#endif // macOS]
199202
fontHasBeenUpdatedBySystem;
200203

packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
2020
#if !TARGET_OS_OSX // [macOS]
2121
@interface RCTUITextField : UITextField <RCTBackedTextInputViewProtocol>
2222
#else // [macOS
23-
#if RCT_SUBCLASS_SECURETEXTFIELD
24-
@interface RCTUISecureTextField : NSSecureTextField <RCTBackedTextInputViewProtocol>
25-
#else
2623
@interface RCTUITextField : NSTextField <RCTBackedTextInputViewProtocol>
27-
#endif // RCT_SUBCLASS_SECURETEXTFIELD
2824
#endif // macOS]
2925

3026

packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.mm

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@
1717

1818
#if TARGET_OS_OSX // [macOS
1919

20-
#if RCT_SUBCLASS_SECURETEXTFIELD
21-
#define RCTUITextFieldCell RCTUISecureTextFieldCell
22-
@interface RCTUISecureTextFieldCell : NSSecureTextFieldCell
23-
#else
2420
@interface RCTUITextFieldCell : NSTextFieldCell
25-
#endif
2621

2722
@property (nonatomic, assign) UIEdgeInsets textContainerInset;
2823
@property (nonatomic, getter=isAutomaticTextReplacementEnabled) BOOL automaticTextReplacementEnabled;
@@ -86,11 +81,7 @@ - (NSText *)setUpFieldEditorAttributes:(NSText *)textObj
8681
@end
8782
#endif // macOS]
8883

89-
#ifdef RCT_SUBCLASS_SECURETEXTFIELD
90-
@implementation RCTUISecureTextField {
91-
#else
9284
@implementation RCTUITextField {
93-
#endif
9485
RCTBackedTextFieldDelegateAdapter *_textInputDelegateAdapter;
9586
NSDictionary<NSAttributedStringKey, id> *_defaultTextAttributes;
9687
#if !TARGET_OS_OSX // [macOS]

packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
// [macOS]
99

1010
#if TARGET_OS_OSX
11-
#define RCT_SUBCLASS_SECURETEXTFIELD 1
12-
#endif
1311

14-
#include <React/RCTUITextField.h>
12+
#import <React/RCTUITextField.h>
13+
14+
@interface RCTUISecureTextField : RCTUITextField
15+
@end
1516

17+
#endif

packages/react-native/Libraries/Text/TextInput/Singleline/macOS/RCTUISecureTextField.m

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
// [macOS]
9+
10+
#if TARGET_OS_OSX
11+
12+
#import <React/RCTUISecureTextField.h>
13+
#import <React/RCTUIKit.h>
14+
15+
#pragma mark - RCTUISecureTextFieldCell
16+
17+
@interface RCTUISecureTextFieldCell : NSSecureTextFieldCell
18+
19+
@property (nonatomic, assign) UIEdgeInsets textContainerInset;
20+
@property (nonatomic, getter=isAutomaticTextReplacementEnabled) BOOL automaticTextReplacementEnabled;
21+
@property (nonatomic, getter=isAutomaticSpellingCorrectionEnabled) BOOL automaticSpellingCorrectionEnabled;
22+
@property (nonatomic, getter=isContinuousSpellCheckingEnabled) BOOL continuousSpellCheckingEnabled;
23+
@property (nonatomic, getter=isGrammarCheckingEnabled) BOOL grammarCheckingEnabled;
24+
@property (nonatomic, strong, nullable) RCTPlatformColor *selectionColor;
25+
@property (nonatomic, strong, nullable) RCTPlatformColor *insertionPointColor;
26+
27+
@end
28+
29+
@implementation RCTUISecureTextFieldCell
30+
31+
- (void)setTextContainerInset:(UIEdgeInsets)textContainerInset
32+
{
33+
_textContainerInset = textContainerInset;
34+
}
35+
36+
- (NSRect)titleRectForBounds:(NSRect)rect
37+
{
38+
return UIEdgeInsetsInsetRect([super titleRectForBounds:rect], self.textContainerInset);
39+
}
40+
41+
- (void)editWithFrame:(NSRect)rect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)delegate event:(NSEvent *)event
42+
{
43+
[super editWithFrame:[self titleRectForBounds:rect] inView:controlView editor:textObj delegate:delegate event:event];
44+
}
45+
46+
- (void)selectWithFrame:(NSRect)rect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)delegate start:(NSInteger)selStart length:(NSInteger)selLength
47+
{
48+
[super selectWithFrame:[self titleRectForBounds:rect] inView:controlView editor:textObj delegate:delegate start:selStart length:selLength];
49+
}
50+
51+
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
52+
{
53+
if (self.drawsBackground) {
54+
if (self.backgroundColor && self.backgroundColor.alphaComponent > 0) {
55+
56+
[self.backgroundColor set];
57+
NSRectFill(cellFrame);
58+
}
59+
}
60+
61+
[super drawInteriorWithFrame:[self titleRectForBounds:cellFrame] inView:controlView];
62+
}
63+
64+
- (NSText *)setUpFieldEditorAttributes:(NSText *)textObj
65+
{
66+
NSTextView *fieldEditor = (NSTextView *)[super setUpFieldEditorAttributes:textObj];
67+
fieldEditor.automaticSpellingCorrectionEnabled = self.isAutomaticSpellingCorrectionEnabled;
68+
fieldEditor.automaticTextReplacementEnabled = self.isAutomaticTextReplacementEnabled;
69+
fieldEditor.continuousSpellCheckingEnabled = self.isContinuousSpellCheckingEnabled;
70+
fieldEditor.grammarCheckingEnabled = self.isGrammarCheckingEnabled;
71+
NSMutableDictionary *selectTextAttributes = fieldEditor.selectedTextAttributes.mutableCopy;
72+
selectTextAttributes[NSBackgroundColorAttributeName] = self.selectionColor ?: [NSColor selectedControlColor];
73+
fieldEditor.selectedTextAttributes = selectTextAttributes;
74+
fieldEditor.insertionPointColor = self.insertionPointColor ?: [NSColor textColor];
75+
return fieldEditor;
76+
}
77+
78+
@end
79+
80+
#pragma mark - RCTUISecureTextField
81+
82+
@implementation RCTUISecureTextField
83+
84+
+ (Class)cellClass
85+
{
86+
return RCTUISecureTextFieldCell.class;
87+
}
88+
89+
@end
90+
91+
#endif // TARGET_OS_OSX

packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ - (BOOL)_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldTe
12191219
// There are multiple Korean input sources (2-Set, 3-Set, etc). Check substring instead instead
12201220
[[[_backedTextInputView inputContext] selectedKeyboardInputSource] containsString:@"com.apple.inputmethod.Korean"] ||
12211221
[_backedTextInputView hasMarkedText] ||
1222-
[_backedTextInputView isKindOfClass:[NSSecureTextField class]] ||
1222+
[_backedTextInputView isKindOfClass:[RCTUISecureTextField class]] ||
12231223
#endif // macOS]
12241224
fontHasBeenUpdatedBySystem;
12251225

0 commit comments

Comments
 (0)