mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
fcead14b0e
Summary: Note: PR to react-native-macos here https://github.com/microsoft/react-native-macos/pull/733 Internally in Microsoft code, we ran into a deadlock where the main queue and the UIManager queue were both trying to access `[RCTI18nUtil sharedInstance]`, and were blocked on each other. This is similar to an earlier issue with RCTScreenScale decsribed [here](https://github.com/facebook/react-native/issues/18096). To summarize: 1- RCTShadowView (on the UIManager queue) and RCTView (on the main queue) both try to access `[RCTI18nUtil sharedInstance]` 2- The UIManager thread gets there first, and lazily initializes the sharedInstance. Meanwhile, the main thread is waiting on a lock possessed by the UIManager thread 3- As part of the initialization, we set an NSUserDefault, which seems to require the (blocked) main thread. 4- Deadlock. For whatever reason, this only happens on debug. I did not figure out why, but I do know based on [this comment](https://github.com/facebook/react-native/issues/18096#issuecomment-368718081), that the UIManagerQueue should never block the main queue. The fix is to not use NSUserDefaults, and simpy use atomic properties instead. We get the thread safety for free, and it also simplifies the code somewhat without changing the public API. The downside is values aren't persisted anymore, but I do not think that was necessary / intended. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> [iOS] [Fixed] - Fix deadlock on RCTi18nUtil Pull Request resolved: https://github.com/facebook/react-native/pull/31032 Test Plan: Ran the RTLExample in RNTester, and ensured switching to RTL still worked, and that setting forceRTL would still work after reloading the bundle. https://user-images.githubusercontent.com/6722175/108775429-aefdae80-7526-11eb-9a89-3114f7ddc2af.mov Reviewed By: javache Differential Revision: D29522152 Pulled By: RSNara fbshipit-source-id: 160840f63a7b1d6721b0fd8294fb11990a4509fa
60 lines
1.5 KiB
Objective-C
60 lines
1.5 KiB
Objective-C
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#import "RCTI18nUtil.h"
|
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
@implementation RCTI18nUtil
|
|
|
|
+ (instancetype)sharedInstance
|
|
{
|
|
static RCTI18nUtil *sharedInstance;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
sharedInstance = [self new];
|
|
[sharedInstance swapLeftAndRightInRTL:true];
|
|
[sharedInstance allowRTL:true];
|
|
});
|
|
|
|
return sharedInstance;
|
|
}
|
|
|
|
/**
|
|
* Check if the app is currently running on an RTL locale.
|
|
* This only happens when the app:
|
|
* - is forcing RTL layout, regardless of the active language (for development purpose)
|
|
* - allows RTL layout when using RTL locale
|
|
*/
|
|
- (BOOL)isRTL
|
|
{
|
|
if ([self isRTLForced]) {
|
|
return YES;
|
|
}
|
|
if ([self isRTLAllowed] && [self isApplicationPreferredLanguageRTL]) {
|
|
return YES;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
// Check if the current device language is RTL
|
|
- (BOOL)isDevicePreferredLanguageRTL
|
|
{
|
|
NSLocaleLanguageDirection direction =
|
|
[NSLocale characterDirectionForLanguage:[[NSLocale preferredLanguages] objectAtIndex:0]];
|
|
return direction == NSLocaleLanguageDirectionRightToLeft;
|
|
}
|
|
|
|
// Check if the current application language is RTL
|
|
- (BOOL)isApplicationPreferredLanguageRTL
|
|
{
|
|
NSWritingDirection direction = [NSParagraphStyle defaultWritingDirectionForLanguage:nil];
|
|
return direction == NSWritingDirectionRightToLeft;
|
|
}
|
|
|
|
@end
|