Skip to content

Commit

Permalink
Allow iOS PlatformColor strings to be ObjC or Swift UIColor selectors (
Browse files Browse the repository at this point in the history
…#28703)

Summary:
Per discussion in react-native-community/releases#186 the iOS `PlatformColor()` function is documented to use the semantic color names provided by the system.   The referenced HIG documentation itself links to the `UIColor` documentation for semantic colors names.   However, these names differ depending on if you are viewing the new Swift API docs or the Objective C docs.   The current Objective C implementation in react-native assumes Objective C UIColor selector names that are suffixed 'Color'.   But in Swift, Apple provides a Swift Extension on UIColor that makes aliases without the the 'Color' suffix and then makes the original selectors invalid presumably via `NS_UNAVAILABLE_SWIFT`.

Since both selector names are valid depending on if you are using Objective C or Swift, let's make both forms be legal for `PlatformColor()`.   In `RCTConvert.m` there is a dictionary of legal selector names.   The code already supports the ability to have names be aliases of other selectors via a RCTSelector metadata key.   The change adds code to the initialization of the map: it iterates over the keys in the map, which are all ObjC style UIColor selectors, and creates aliases by duplicating the entries, creating key names by stripping off the ObjC "Color" suffix, adds the RCTSelector key referring to the original and then appends these new Swift aliases to the map.

## Changelog

[iOS] [Changed] - Allow iOS PlatformColor strings to be ObjC or Swift UIColor selectors
Pull Request resolved: #28703

Test Plan:
The PlatformColorExample.js is updated to use the new, shorter Swift selector names.   There are still other examples in the same file and in unit tests that exercise the ObjC selector names.

<img width="492" alt="PlatformColor" src="https://user-images.githubusercontent.com/30053638/79809089-89ab7d00-8324-11ea-8a9d-120b92edeedf.png">

Reviewed By: shergin

Differential Revision: D21147404

Pulled By: TheSavior

fbshipit-source-id: 0273ec855e426b3a7ba97a87645859e05bcd4126
  • Loading branch information
tom-un authored and facebook-github-bot committed Apr 21, 2020
1 parent d639063 commit 25793ea
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 52 deletions.
100 changes: 50 additions & 50 deletions RNTester/js/examples/PlatformColor/PlatformColorExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,94 +22,94 @@ function PlatformColorsExample() {
colors = [
// https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors
// Label Colors
{label: 'labelColor', color: PlatformColor('labelColor')},
{label: 'label', color: PlatformColor('label')},
{
label: 'secondaryLabelColor',
color: PlatformColor('secondaryLabelColor'),
label: 'secondaryLabel',
color: PlatformColor('secondaryLabel'),
},
{
label: 'tertiaryLabelColor',
color: PlatformColor('tertiaryLabelColor'),
label: 'tertiaryLabel',
color: PlatformColor('tertiaryLabel'),
},
{
label: 'quaternaryLabelColor',
color: PlatformColor('quaternaryLabelColor'),
label: 'quaternaryLabel',
color: PlatformColor('quaternaryLabel'),
},
// Fill Colors
{label: 'systemFillColor', color: PlatformColor('systemFillColor')},
{label: 'systemFill', color: PlatformColor('systemFill')},
{
label: 'secondarySystemFillColor',
color: PlatformColor('secondarySystemFillColor'),
label: 'secondarySystemFill',
color: PlatformColor('secondarySystemFill'),
},
{
label: 'tertiarySystemFillColor',
color: PlatformColor('tertiarySystemFillColor'),
label: 'tertiarySystemFill',
color: PlatformColor('tertiarySystemFill'),
},
{
label: 'quaternarySystemFillColor',
color: PlatformColor('quaternarySystemFillColor'),
label: 'quaternarySystemFill',
color: PlatformColor('quaternarySystemFill'),
},
// Text Colors
{
label: 'placeholderTextColor',
color: PlatformColor('placeholderTextColor'),
label: 'placeholderText',
color: PlatformColor('placeholderText'),
},
// Standard Content Background Colors
{
label: 'systemBackgroundColor',
color: PlatformColor('systemBackgroundColor'),
label: 'systemBackground',
color: PlatformColor('systemBackground'),
},
{
label: 'secondarySystemBackgroundColor',
color: PlatformColor('secondarySystemBackgroundColor'),
label: 'secondarySystemBackground',
color: PlatformColor('secondarySystemBackground'),
},
{
label: 'tertiarySystemBackgroundColor',
color: PlatformColor('tertiarySystemBackgroundColor'),
label: 'tertiarySystemBackground',
color: PlatformColor('tertiarySystemBackground'),
},
// Grouped Content Background Colors
{
label: 'systemGroupedBackgroundColor',
color: PlatformColor('systemGroupedBackgroundColor'),
label: 'systemGroupedBackground',
color: PlatformColor('systemGroupedBackground'),
},
{
label: 'secondarySystemGroupedBackgroundColor',
color: PlatformColor('secondarySystemGroupedBackgroundColor'),
label: 'secondarySystemGroupedBackground',
color: PlatformColor('secondarySystemGroupedBackground'),
},
{
label: 'tertiarySystemGroupedBackgroundColor',
color: PlatformColor('tertiarySystemGroupedBackgroundColor'),
label: 'tertiarySystemGroupedBackground',
color: PlatformColor('tertiarySystemGroupedBackground'),
},
// Separator Colors
{label: 'separatorColor', color: PlatformColor('separatorColor')},
{label: 'separator', color: PlatformColor('separator')},
{
label: 'opaqueSeparatorColor',
color: PlatformColor('opaqueSeparatorColor'),
label: 'opaqueSeparator',
color: PlatformColor('opaqueSeparator'),
},
// Link Color
{label: 'linkColor', color: PlatformColor('linkColor')},
{label: 'link', color: PlatformColor('link')},
// Nonadaptable Colors
{label: 'darkTextColor', color: PlatformColor('darkTextColor')},
{label: 'lightTextColor', color: PlatformColor('lightTextColor')},
{label: 'darkText', color: PlatformColor('darkText')},
{label: 'lightText', color: PlatformColor('lightText')},
// https://developer.apple.com/documentation/uikit/uicolor/standard_colors
// Adaptable Colors
{label: 'systemBlueColor', color: PlatformColor('systemBlueColor')},
{label: 'systemBrownColor', color: PlatformColor('systemBrownColor')},
{label: 'systemGreenColor', color: PlatformColor('systemGreenColor')},
{label: 'systemIndigoColor', color: PlatformColor('systemIndigoColor')},
{label: 'systemOrangeColor', color: PlatformColor('systemOrangeColor')},
{label: 'systemPinkColor', color: PlatformColor('systemPinkColor')},
{label: 'systemPurpleColor', color: PlatformColor('systemPurpleColor')},
{label: 'systemRedColor', color: PlatformColor('systemRedColor')},
{label: 'systemTealColor', color: PlatformColor('systemTealColor')},
{label: 'systemYellowColor', color: PlatformColor('systemYellowColor')},
{label: 'systemBlue', color: PlatformColor('systemBlue')},
{label: 'systemBrown', color: PlatformColor('systemBrown')},
{label: 'systemGreen', color: PlatformColor('systemGreen')},
{label: 'systemIndigo', color: PlatformColor('systemIndigo')},
{label: 'systemOrange', color: PlatformColor('systemOrange')},
{label: 'systemPink', color: PlatformColor('systemPink')},
{label: 'systemPurple', color: PlatformColor('systemPurple')},
{label: 'systemRed', color: PlatformColor('systemRed')},
{label: 'systemTeal', color: PlatformColor('systemTeal')},
{label: 'systemYellow', color: PlatformColor('systemYellow')},
// Adaptable Gray Colors
{label: 'systemGrayColor', color: PlatformColor('systemGrayColor')},
{label: 'systemGray2Color', color: PlatformColor('systemGray2Color')},
{label: 'systemGray3Color', color: PlatformColor('systemGray3Color')},
{label: 'systemGray4Color', color: PlatformColor('systemGray4Color')},
{label: 'systemGray5Color', color: PlatformColor('systemGray5Color')},
{label: 'systemGray6Color', color: PlatformColor('systemGray6Color')},
{label: 'systemGray', color: PlatformColor('systemGray')},
{label: 'systemGray2', color: PlatformColor('systemGray2')},
{label: 'systemGray3', color: PlatformColor('systemGray3')},
{label: 'systemGray4', color: PlatformColor('systemGray4')},
{label: 'systemGray5', color: PlatformColor('systemGray5')},
{label: 'systemGray6', color: PlatformColor('systemGray6')},
];
} else if (Platform.OS === 'android') {
colors = [
Expand Down
21 changes: 19 additions & 2 deletions React/Base/RCTConvert.m
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ +(type)type : (id)json \
{
static NSDictionary<NSString *, NSDictionary *> *colorMap = nil;
if (colorMap == nil) {
colorMap = @{
NSMutableDictionary<NSString *, NSDictionary *> *map = [@{
// https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors
// Label Colors
@"labelColor" : @{
Expand Down Expand Up @@ -729,7 +729,22 @@ +(type)type : (id)json \
// iOS 13.0
RCTFallbackARGB : @(0xFFf2f2f7)
},
} mutableCopy];
// The color names are the Objective-C UIColor selector names,
// but Swift selector names are valid as well, so make aliases.
static NSString *const RCTColorSuffix = @"Color";
NSMutableDictionary<NSString *, NSDictionary *> *aliases = [NSMutableDictionary new];
for (NSString *objcSelector in map) {
RCTAssert([objcSelector hasSuffix:RCTColorSuffix], @"A selector in the color map did not end with the suffix Color.");
NSMutableDictionary *entry = [map[objcSelector] mutableCopy];
RCTAssert([entry objectForKey:RCTSelector] == nil, @"Entry should not already have an RCTSelector");
NSString *swiftSelector = [objcSelector substringToIndex:[objcSelector length] - [RCTColorSuffix length]];
entry[RCTSelector] = objcSelector;
aliases[swiftSelector] = entry;
}
[map addEntriesFromDictionary:aliases];
#if DEBUG
[map addEntriesFromDictionary:@{
// The follow exist for Unit Tests
@"unitTestFallbackColor" : @{RCTFallback : @"gridColor"},
@"unitTestFallbackColorIOS" : @{RCTFallback : @"blueColor"},
Expand All @@ -743,9 +758,11 @@ +(type)type : (id)json \
RCTIndex : @1,
RCTFallback : @"controlAlternatingRowBackgroundColors"
},
}];
#endif
};
colorMap = [map copy];
}

return colorMap;
}

Expand Down

0 comments on commit 25793ea

Please sign in to comment.