-
Notifications
You must be signed in to change notification settings - Fork 161
Fix -[RCTDynamicColor effectiveColor] being called off UI thread #438
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
Fix -[RCTDynamicColor effectiveColor] being called off UI thread #438
Conversation
|
I'm not sure what the usage would be to call effectiveColor when not on the UI thread. The call site that's trying to do this seems like the issue to be fixed, not RCTDynamicColor. Dynamic colors by definition don't resolve to a specific color until resolved within a given UI context. So in this case, we're just caching the last context in which this color was resolved and hoping that it stays accurate. That's by no means guaranteed to be true. Different view hierarchies within the same window/application can have different appearances or the user could change the system setting at runtime, so depending on a cached version of the color seems likely to provide invalid colors. |
|
+1 to what @markavitale said. This seems like this would just silence the flaw and make such bugs more difficult to detect |
anandrajeswaran
left a comment
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.
There shouldn't be a use case for calling this off the UI thread and adding a cache in here just increases the odds of a subtle bug.
|
It gets called from |
|
@tido64 so then the real bug would be the shadow view should not be dealing with color attributes at all since that doesn't affect sizing? |
df1dd35 to
35d57dd
Compare
You're right. It seems that we only need |
|
@tido64 can we go one more level up? RCTDynamicColor should be able to be completely unaware of other threads. RCTBaseTextShadowView is the one that is asking for it on a background thread and that's what we should fix |
Libraries/Text/BaseText/RCTBaseTextShadowView.m:100 if (text) {
NSAttributedString *rawTextAttributedString =
[[NSAttributedString alloc] initWithString:[textAttributes applyTextAttributesToText:text]
attributes:textAttributes.effectiveTextAttributes];
[attributedText appendAttributedString:rawTextAttributedString];
}This piece of code works fine with any |
|
@tido64 or just not include color attributes? We still should not be referring to NSColors on background threads even if that currently happens to not throw an error of some sort. |
|
The [RCTDynamicColor effectiveColor] method is being called because [NSColor colorSpaceName] is used in NSColor's NSObject hash function. And the hash is being called because NSAttributedString's implementation uses hashes for its attribute dictionary. A simple fix is to override - (NSUInteger)hash {
NSUInteger prime = 31, result = 1;
result = prime * result + [_aquaColor hash];
result = prime * result + [_darkAquaColor hash];
return result;
}When overriding - (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [self isEqualToDynamicColor:other];
}
- (BOOL)isEqualToDynamicColor:(RCTDynamicColor *)other {
if (self == other)
return YES;
if ([_aquaColor isNotEqualTo:other->_aquaColor])
return NO;
if ([_darkAquaColor isNotEqualTo:other->_darkAquaColor])
return NO;
return YES;
}Long term react-native layout should be manipulating the NSAttributedStrings and NSColor/UIColors only on the main thread, but such a change is way out of scope of this fix. But such a think can and probably is being done as part of the Fabric rearchitecture. |
35d57dd to
85dca79
Compare
Thanks, @tom-un. Your solution does work. |
Summary
Xcode logs warnings to console about the use of the appearance API on a non-UI thread. This fix should allow the current behaviour.
Resolves #335
Changelog
[macOS] [Fixed] - Allow
-[RCTDynamicColor effectiveColor]to be called off UI threadTest Plan
Xcode should warn about the use of the appearance API on a non-UI thread.
Microsoft Reviewers: Open in CodeFlow