-
Notifications
You must be signed in to change notification settings - Fork 24.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[iOS] Fabric: Fixes crash of dynamic color when light/dark mode changed #48496
Changes from 3 commits
795e684
adeafa9
a720b3d
8949170
3e72b4d
dad55b5
fabf86f
6329f2e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,18 +73,24 @@ int32_t ColorFromUIColor(UIColor *color) | |
((int)round((float)rgba[1] * ratio) & 0xff) << 8 | ((int)round((float)rgba[2] * ratio) & 0xff); | ||
} | ||
|
||
int32_t ColorFromUIColor(const std::shared_ptr<void> &uiColor) | ||
int32_t ColorFromUIColorForSpecificTraitCollection( | ||
const std::shared_ptr<void> &uiColor, | ||
UITraitCollection *traitCollection) | ||
{ | ||
UIColor *color = (UIColor *)unwrapManagedObject(uiColor); | ||
if (color) { | ||
UITraitCollection *currentTraitCollection = [UITraitCollection currentTraitCollection]; | ||
color = [color resolvedColorWithTraitCollection:currentTraitCollection]; | ||
color = [color resolvedColorWithTraitCollection:traitCollection]; | ||
return ColorFromUIColor(color); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int32_t ColorFromUIColor(const std::shared_ptr<void> &uiColor) | ||
{ | ||
return ColorFromUIColorForSpecificTraitCollection(uiColor, [UITraitCollection currentTraitCollection]); | ||
} | ||
|
||
UIColor *_Nullable UIColorFromComponentsColor(const facebook::react::ColorComponents &components) | ||
{ | ||
if (components.colorSpace == ColorSpace::DisplayP3) { | ||
|
@@ -142,6 +148,40 @@ int32_t ColorFromUIColor(const std::shared_ptr<void> &uiColor) | |
return static_cast<float>(rgba[channelId]); | ||
} | ||
|
||
int32_t Color::getUIColorHash() const | ||
{ | ||
if (!uiColorHashValue_) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this work?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The point here is: the UIColor does not change when the UITraitCollection changes. The uiColor is the actual invariant here, we don't need to compute the hash resolving the uicolor against all the trait collections. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @javache @cipolleschi I don't know details about how UIColor wether implements For example: Two methods like below, [self dynamicColor].hash is not equal to [self dynamicColor1].hash. Actually they are the same color. So it may have potential issues if we use the hash value to check equality?
PS. The crash disappeared if we return color.hash. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So UIColor hashValue is probably just falling back to NSObject, which means the value won't change over the objects lifetime, but also can't be reliably used to compare objects that are equal :( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My concern is that hashing is supposed to be cheap, and we use it implicitly in a number of different places. This makes the common case of a non-platform color significantly more expensive. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The hash is computed only once, when needed the first time, and then cached in the |
||
return uiColorHashValue_; | ||
} | ||
|
||
static UITraitCollection *darkModeTraitCollection = | ||
[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark]; | ||
auto darkColor = ColorFromUIColorForSpecificTraitCollection(uiColor_, darkModeTraitCollection); | ||
|
||
static UITraitCollection *lightModeTraitCollection = | ||
[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]; | ||
auto lightColor = ColorFromUIColorForSpecificTraitCollection(uiColor_, lightModeTraitCollection); | ||
|
||
static UITraitCollection *darkModeAccessibilityContrastTraitCollection = | ||
[UITraitCollection traitCollectionWithTraitsFromCollections:@[ | ||
darkModeTraitCollection, | ||
[UITraitCollection traitCollectionWithAccessibilityContrast:UIAccessibilityContrastHigh] | ||
]]; | ||
auto darkAccessibilityContrastColor = | ||
ColorFromUIColorForSpecificTraitCollection(uiColor_, darkModeAccessibilityContrastTraitCollection); | ||
|
||
static UITraitCollection *lightModeAccessibilityContrastTraitCollection = | ||
[UITraitCollection traitCollectionWithTraitsFromCollections:@[ | ||
lightModeTraitCollection, | ||
[UITraitCollection traitCollectionWithAccessibilityContrast:UIAccessibilityContrastHigh] | ||
]]; | ||
auto lightAccessibilityContrastColor = | ||
ColorFromUIColorForSpecificTraitCollection(uiColor_, lightModeAccessibilityContrastTraitCollection); | ||
uiColorHashValue_ = facebook::react::hash_combine( | ||
darkColor, lightColor, darkAccessibilityContrastColor, lightAccessibilityContrastColor); | ||
return uiColorHashValue_; | ||
} | ||
|
||
} // namespace facebook::react | ||
|
||
NS_ASSUME_NONNULL_END |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@javache No value in calling hash_combine again with seed 0.