Skip to content

Commit

Permalink
fix: over reporting trait changes (#39439)
Browse files Browse the repository at this point in the history
Summary:
Closes #35972
Closes #36713

This PR addresses a couple of issues with `useColorScheme` and the `Appearance` API.

- #38214 introduced a regression. Using to `RCTExecuteOnMainQueue` was a mistake as we need this to happen synchronously to return the result. Doing it async causes the `traitCollection` to remain uninitialized.
- The `useColorScheme` hook is updating when the app is in the background on iOS and the OS is taking the snapshots for the app switcher. This causes a flash when returning to the app as the correct color is set again. Here, we can check for the app state in `traitCollectionDidChange` and not send these events when in the background.
- Removed a line that was left over after some OS version checks were removed when support for iOS 12 was dropped.

## Changelog:

[IOS] [FIXED] - Don't send the `RCTUserInterfaceStyleDidChangeNotification` when the app is in the background.

Pull Request resolved: #39439

Test Plan: Tested on `rn-tester`, logged the changes whenever `useColorScheme` updates. It no longer happens when the app is in the background. The returned interface style on the initial render is always correct now.

Reviewed By: NickGerleman

Differential Revision: D49454281

Pulled By: javache

fbshipit-source-id: 87e24158a49c50608c79e73fb484442f5aad36a6
  • Loading branch information
alanjhughes authored and facebook-github-bot committed Sep 26, 2023
1 parent 27b631e commit 6118aff
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 11 deletions.
3 changes: 3 additions & 0 deletions packages/react-native/React/Base/RCTRootView.m
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ - (void)contentViewInvalidated
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
[super traitCollectionDidChange:previousTraitCollection];
if (RCTSharedApplication().applicationState == UIApplicationStateBackground) {
return;
}

[[NSNotificationCenter defaultCenter]
postNotificationName:RCTUserInterfaceStyleDidChangeNotification
Expand Down
1 change: 1 addition & 0 deletions packages/react-native/React/CoreModules/RCTAppearance.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ RCT_EXTERN NSString *RCTCurrentOverrideAppearancePreference();
RCT_EXTERN NSString *RCTColorSchemePreference(UITraitCollection *traitCollection);

@interface RCTAppearance : RCTEventEmitter <RCTBridgeModule>
- (instancetype)init;
@end
29 changes: 18 additions & 11 deletions packages/react-native/React/CoreModules/RCTAppearance.mm
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ void RCTOverrideAppearancePreference(NSString *const colorSchemeOverride)
return RCTAppearanceColorSchemeLight;
}

traitCollection = traitCollection ?: [UITraitCollection currentTraitCollection];
return appearances[@(traitCollection.userInterfaceStyle)] ?: RCTAppearanceColorSchemeLight;

// Default to light on older OS version - same behavior as Android.
return RCTAppearanceColorSchemeLight;
}

@interface RCTAppearance () <NativeAppearanceSpec>
Expand All @@ -71,6 +67,19 @@ @implementation RCTAppearance {
NSString *_currentColorScheme;
}

- (instancetype)init
{
if ((self = [super init])) {
UITraitCollection *traitCollection = RCTSharedApplication().delegate.window.traitCollection;
_currentColorScheme = RCTColorSchemePreference(traitCollection);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appearanceChanged:)
name:RCTUserInterfaceStyleDidChangeNotification
object:nil];
}
return self;
}

RCT_EXPORT_MODULE(Appearance)

+ (BOOL)requiresMainQueueSetup
Expand Down Expand Up @@ -100,9 +109,6 @@ - (dispatch_queue_t)methodQueue

RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getColorScheme)
{
if (_currentColorScheme == nil) {
_currentColorScheme = RCTColorSchemePreference(nil);
}
return _currentColorScheme;
}

Expand All @@ -129,14 +135,15 @@ - (void)appearanceChanged:(NSNotification *)notification

- (void)startObserving
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appearanceChanged:)
name:RCTUserInterfaceStyleDidChangeNotification
object:nil];
}

- (void)stopObserving
{
}

- (void)invalidate
{
[super invalidate];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

Expand Down

0 comments on commit 6118aff

Please sign in to comment.