diff --git a/Libraries/Text/RCTTextField.h b/Libraries/Text/RCTTextField.h index 0c8266d7e..3aba72bba 100644 --- a/Libraries/Text/RCTTextField.h +++ b/Libraries/Text/RCTTextField.h @@ -11,7 +11,7 @@ @class RCTEventDispatcher; -@interface RCTTextField : UITextField +@interface RCTTextField : UITextField @property (nonatomic, assign) BOOL caretHidden; @property (nonatomic, assign) BOOL autoCorrect; @@ -22,5 +22,6 @@ @property (nonatomic, strong) NSNumber *maxLength; - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; +- (void)textFieldDidChange; @end diff --git a/Libraries/Text/RCTTextField.m b/Libraries/Text/RCTTextField.m index 57e0499bd..94b204fce 100644 --- a/Libraries/Text/RCTTextField.m +++ b/Libraries/Text/RCTTextField.m @@ -27,12 +27,11 @@ if ((self = [super initWithFrame:CGRectZero])) { RCTAssert(eventDispatcher, @"eventDispatcher is a required parameter"); _eventDispatcher = eventDispatcher; - [self addTarget:self action:@selector(_textFieldDidChange) forControlEvents:UIControlEventEditingChanged]; - [self addTarget:self action:@selector(_textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin]; - [self addTarget:self action:@selector(_textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd]; - [self addTarget:self action:@selector(_textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit]; + [self addTarget:self action:@selector(textFieldDidChange) forControlEvents:UIControlEventEditingChanged]; + [self addTarget:self action:@selector(textFieldBeginEditing) forControlEvents:UIControlEventEditingDidBegin]; + [self addTarget:self action:@selector(textFieldEndEditing) forControlEvents:UIControlEventEditingDidEnd]; + [self addTarget:self action:@selector(textFieldSubmitEditing) forControlEvents:UIControlEventEditingDidEndOnExit]; _reactSubviews = [[NSMutableArray alloc] init]; - self.delegate = self; } return self; } @@ -40,31 +39,6 @@ RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame) RCT_NOT_IMPLEMENTED(-initWithCoder:(NSCoder *)aDecoder) -- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string -{ - if (_maxLength == nil || [string isEqualToString:@"\n"]) { // Make sure forms can be submitted via return - return YES; - } - NSUInteger allowedLength = _maxLength.integerValue - textField.text.length + range.length; - if (string.length > allowedLength) { - if (string.length > 1) { - // Truncate the input string so the result is exactly maxLength - NSString *limitedString = [string substringToIndex:allowedLength]; - NSMutableString *newString = textField.text.mutableCopy; - [newString replaceCharactersInRange:range withString:limitedString]; - textField.text = newString; - // Collapse selection at end of insert to match normal paste behavior - UITextPosition *insertEnd = [textField positionFromPosition:textField.beginningOfDocument - offset:(range.location + allowedLength)]; - textField.selectedTextRange = [textField textRangeFromPosition:insertEnd toPosition:insertEnd]; - [self _textFieldDidChange]; - } - return NO; - } else { - return YES; - } -} - - (void)setText:(NSString *)text { NSInteger eventLag = _nativeEventCount - _mostRecentEventCount; @@ -154,7 +128,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self) return self.autocorrectionType == UITextAutocorrectionTypeYes; } -- (void)_textFieldDidChange +- (void)textFieldDidChange { _nativeEventCount++; [_eventDispatcher sendTextEventWithType:RCTTextEventTypeChange @@ -163,14 +137,14 @@ static void RCTUpdatePlaceholder(RCTTextField *self) eventCount:_nativeEventCount]; } -- (void)_textFieldEndEditing +- (void)textFieldEndEditing { [_eventDispatcher sendTextEventWithType:RCTTextEventTypeEnd reactTag:self.reactTag text:self.text eventCount:_nativeEventCount]; } -- (void)_textFieldSubmitEditing +- (void)textFieldSubmitEditing { [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit reactTag:self.reactTag @@ -178,7 +152,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self) eventCount:_nativeEventCount]; } -- (void)_textFieldBeginEditing +- (void)textFieldBeginEditing { if (_selectTextOnFocus) { dispatch_async(dispatch_get_main_queue(), ^{ diff --git a/Libraries/Text/RCTTextFieldManager.m b/Libraries/Text/RCTTextFieldManager.m index 723ec10f9..8ce0b1430 100644 --- a/Libraries/Text/RCTTextFieldManager.m +++ b/Libraries/Text/RCTTextFieldManager.m @@ -14,13 +14,44 @@ #import "RCTSparseArray.h" #import "RCTTextField.h" +@interface RCTTextFieldManager() + +@end + @implementation RCTTextFieldManager RCT_EXPORT_MODULE() - (UIView *)view { - return [[RCTTextField alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; + RCTTextField *textField = [[RCTTextField alloc] initWithEventDispatcher:self.bridge.eventDispatcher]; + textField.delegate = self; + return textField; +} + +- (BOOL)textField:(RCTTextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +{ + if (textField.maxLength == nil || [string isEqualToString:@"\n"]) { // Make sure forms can be submitted via return + return YES; + } + NSUInteger allowedLength = textField.maxLength.integerValue - textField.text.length + range.length; + if (string.length > allowedLength) { + if (string.length > 1) { + // Truncate the input string so the result is exactly maxLength + NSString *limitedString = [string substringToIndex:allowedLength]; + NSMutableString *newString = textField.text.mutableCopy; + [newString replaceCharactersInRange:range withString:limitedString]; + textField.text = newString; + // Collapse selection at end of insert to match normal paste behavior + UITextPosition *insertEnd = [textField positionFromPosition:textField.beginningOfDocument + offset:(range.location + allowedLength)]; + textField.selectedTextRange = [textField textRangeFromPosition:insertEnd toPosition:insertEnd]; + [textField textFieldDidChange]; + } + return NO; + } else { + return YES; + } } RCT_EXPORT_VIEW_PROPERTY(caretHidden, BOOL)