From ad848ddb7b9949be51ce43f72d34d0580fa2631d Mon Sep 17 00:00:00 2001 From: Levi Buzolic Date: Tue, 19 Feb 2019 23:49:43 -0800 Subject: [PATCH] Map TextInput textContentType strings to Objective-C constants (#22611) Summary: This is an updated version of #22579 which uses compile conditionals to prevent `use of undeclared identifier` errors when compiling on older versions of Xcode. -------- Currently the only `textContentType` values that work are: `username`, `password`, `location`, `name` and `nickname`. This is due to the strings provided by React Native not matching up with the underlying string constants used in iOS (with the exception of the aforementioned types). Issue #22578 has more detail examples/explanation. Pull Request resolved: https://github.com/facebook/react-native/pull/22611 Differential Revision: D13460949 Pulled By: cpojer fbshipit-source-id: e6d1108422b850ebc3aea05693ed05118b77b5de --- .../Text/TextInput/RCTBaseTextInputView.m | 62 ++++++++++++++++++- RNTester/js/TextInputExample.ios.js | 15 +++++ 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.m b/Libraries/Text/TextInput/RCTBaseTextInputView.m index c1c3b00c850568..1ac2dd18edc570 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -141,9 +141,9 @@ - (void)setAttributedText:(NSAttributedString *)attributedText [attributedTextCopy removeAttribute:RCTTextAttributesTagAttributeName range:NSMakeRange(0, attributedTextCopy.length)]; - + textNeedsUpdate = ([self textOf:attributedTextCopy equals:backedTextInputViewTextCopy] == NO); - + if (eventLag == 0 && textNeedsUpdate) { UITextRange *selection = self.backedTextInputView.selectedTextRange; NSInteger oldTextLength = self.backedTextInputView.attributedText.string.length; @@ -203,9 +203,65 @@ - (void)setTextContentType:(NSString *)type { #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 if (@available(iOS 10.0, *)) { + + static dispatch_once_t onceToken; + static NSDictionary *contentTypeMap; + + dispatch_once(&onceToken, ^{ + contentTypeMap = @{@"none": @"", + @"URL": UITextContentTypeURL, + @"addressCity": UITextContentTypeAddressCity, + @"addressCityAndState":UITextContentTypeAddressCityAndState, + @"addressState": UITextContentTypeAddressState, + @"countryName": UITextContentTypeCountryName, + @"creditCardNumber": UITextContentTypeCreditCardNumber, + @"emailAddress": UITextContentTypeEmailAddress, + @"familyName": UITextContentTypeFamilyName, + @"fullStreetAddress": UITextContentTypeFullStreetAddress, + @"givenName": UITextContentTypeGivenName, + @"jobTitle": UITextContentTypeJobTitle, + @"location": UITextContentTypeLocation, + @"middleName": UITextContentTypeMiddleName, + @"name": UITextContentTypeName, + @"namePrefix": UITextContentTypeNamePrefix, + @"nameSuffix": UITextContentTypeNameSuffix, + @"nickname": UITextContentTypeNickname, + @"organizationName": UITextContentTypeOrganizationName, + @"postalCode": UITextContentTypePostalCode, + @"streetAddressLine1": UITextContentTypeStreetAddressLine1, + @"streetAddressLine2": UITextContentTypeStreetAddressLine2, + @"sublocality": UITextContentTypeSublocality, + @"telephoneNumber": UITextContentTypeTelephoneNumber, + }; + + #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ + if (@available(iOS 11.0, *)) { + NSDictionary * iOS11extras = @{@"username": UITextContentTypeUsername, + @"password": UITextContentTypePassword}; + + NSMutableDictionary * iOS11baseMap = [contentTypeMap mutableCopy]; + [iOS11baseMap addEntriesFromDictionary:iOS11extras]; + + contentTypeMap = [iOS11baseMap copy]; + } + #endif + + #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000 /* __IPHONE_12_0 */ + if (@available(iOS 12.0, *)) { + NSDictionary * iOS12extras = @{@"newPassword": UITextContentTypeNewPassword, + @"oneTimeCode": UITextContentTypeOneTimeCode}; + + NSMutableDictionary * iOS12baseMap = [contentTypeMap mutableCopy]; + [iOS12baseMap addEntriesFromDictionary:iOS12extras]; + + contentTypeMap = [iOS12baseMap copy]; + } + #endif + }); + // Setting textContentType to an empty string will disable any // default behaviour, like the autofill bar for password inputs - self.backedTextInputView.textContentType = [type isEqualToString:@"none"] ? @"" : type; + self.backedTextInputView.textContentType = contentTypeMap[type] ?: type; } #endif } diff --git a/RNTester/js/TextInputExample.ios.js b/RNTester/js/TextInputExample.ios.js index b7a61032e98c6a..5529db69a064ca 100644 --- a/RNTester/js/TextInputExample.ios.js +++ b/RNTester/js/TextInputExample.ios.js @@ -1085,4 +1085,19 @@ exports.examples = [ ); }, }, + { + title: 'Text Content Type', + render: function() { + return ( + + + + + + + + + ); + }, + }, ];