mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fabric: Fixes crash of dynamic color when light/dark mode changed (#48496)
Summary: The reason is when light/dark mode changed, the `hash` value also changed because we used `color.getColor()`. leads to size balanced break. ``` Assertion failed: (index_.size() == lru_.size()), function size, file EvictingCacheMap.h, line 439. (lldb) bt * thread https://github.com/facebook/react-native/issues/1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT frame #0: 0x00000001089a9108 libsystem_kernel.dylib`__pthread_kill + 8 frame https://github.com/facebook/react-native/issues/1: 0x0000000105de3408 libsystem_pthread.dylib`pthread_kill + 256 frame https://github.com/facebook/react-native/issues/2: 0x000000018016c4ec libsystem_c.dylib`abort + 104 frame https://github.com/facebook/react-native/issues/3: 0x000000018016b934 libsystem_c.dylib`__assert_rtn + 268 * frame https://github.com/facebook/react-native/issues/4: 0x00000001073e386c React_FabricComponents`folly::EvictingCacheMap<facebook::react::AttributedString, std::__1::shared_ptr<void>, folly::HeterogeneousAccessHash<facebook::react::AttributedString, void>, folly::HeterogeneousAccessEqualTo<facebook::react::AttributedString, void>>::size(this=0x0000600003900348) const at EvictingCacheMap.h:439:5 frame https://github.com/facebook/react-native/issues/5: 0x00000001073e34f4 React_FabricComponents`void folly::EvictingCacheMap<facebook::react::AttributedString, std::__1::shared_ptr<void>, folly::HeterogeneousAccessHash<facebook::react::AttributedString, void>, folly::HeterogeneousAccessEqualTo<facebook::react::AttributedString, void>>::setImpl<facebook::react::AttributedString>(this=0x0000600003900348, key=0x000000016b9f20a8, value=nullptr, promote=true, pruneHook=folly::EvictingCacheMap<facebook::react::AttributedString, std::__1::shared_ptr<void>, folly::HeterogeneousAccessHash<facebook::react::AttributedString, void>, folly::HeterogeneousAccessEqualTo<facebook::react::AttributedString, void> >::PruneHookCall @ 0x000000016b9f1cc8) at EvictingCacheMap.h:674:27 frame https://github.com/facebook/react-native/issues/6: 0x00000001073deb88 React_FabricComponents`folly::EvictingCacheMap<facebook::react::AttributedString, std::__1::shared_ptr<void>, folly::HeterogeneousAccessHash<facebook::react::AttributedString, void>, folly::HeterogeneousAccessEqualTo<facebook::react::AttributedString, void>>::set(this=0x0000600003900348, key=0x000000016b9f20a8, value=ptr = 0x60000024ae20 strong=2 weak=1, promote=true, pruneHook=folly::EvictingCacheMap<facebook::react::AttributedString, std::__1::shared_ptr<void>, folly::HeterogeneousAccessHash<facebook::react::AttributedString, void>, folly::HeterogeneousAccessEqualTo<facebook::react::AttributedString, void> >::PruneHookCall @ 0x000000016b9f1d98) at EvictingCacheMap.h:346:5 frame https://github.com/facebook/react-native/issues/7: 0x00000001073d91dc React_FabricComponents`facebook::react::SimpleThreadSafeCache<facebook::react::AttributedString, std::__1::shared_ptr<void>, 256>::get(this=0x0000600003900348, key=0x000000016b9f20a8, generator= Lambda in File RCTTextLayoutManager.mm at Line 337) const at SimpleThreadSafeCache.h:40:12 frame https://github.com/facebook/react-native/issues/8: 0x00000001073d9058 React_FabricComponents`-[RCTTextLayoutManager _nsAttributedStringFromAttributedString:](self=0x0000600003900340, _cmd="_nsAttributedStringFromAttributedString:", attributedString=AttributedString @ 0x000000016b9f20a8) at RCTTextLayoutManager.mm:337:42 frame https://github.com/facebook/react-native/issues/9: 0x00000001073d6378 React_FabricComponents`-[RCTTextLayoutManager drawAttributedString:paragraphAttributes:frame:drawHighlightPath:](self=0x0000600003900340, _cmd="drawAttributedString:paragraphAttributes:frame:drawHighlightPath:", attributedString=AttributedString @ 0x000000016b9f23a8, paragraphAttributes=ParagraphAttributes @ 0x000000016b9f2378, frame=(origin = (x = 0, y = 0), size = (width = 92, height = 21.666748046875)), block=0x00000001061602d0) at RCTTextLayoutManager.mm:73:56 frame https://github.com/facebook/react-native/issues/10: 0x000000010616020c RCTFabric`-[RCTParagraphTextView drawRect:](self=0x000000012beb9dc0, _cmd="drawRect:", rect=(origin = (x = 0, y = 0.000081380208335701809), size = (width = 92, height = 21.666666666666664))) at RCTParagraphComponentView.mm:346:3 frame https://github.com/facebook/react-native/issues/11: 0x0000000186043e60 UIKitCore`-[UIView(CALayerDelegate) drawLayer:inContext:] + 584 frame https://github.com/facebook/react-native/issues/12: 0x000000018af40080 QuartzCore`CABackingStoreUpdate_ + 244 frame https://github.com/facebook/react-native/issues/13: 0x000000018b0bec88 QuartzCore`invocation function for block in CA::Layer::display_() + 108 frame https://github.com/facebook/react-native/issues/14: 0x000000018b0b5524 QuartzCore`-[CALayer _display] + 1596 frame https://github.com/facebook/react-native/issues/15: 0x000000018b0c7e74 QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 392 frame https://github.com/facebook/react-native/issues/16: 0x000000018affca50 QuartzCore`CA::Context::commit_transaction(CA::Transaction*, double, double*) + 464 frame https://github.com/facebook/react-native/issues/17: 0x000000018b02b260 QuartzCore`CA::Transaction::commit() + 652 frame https://github.com/facebook/react-native/issues/18: 0x000000018b02c7b4 QuartzCore`CA::Transaction::flush_as_runloop_observer(bool) + 68 frame https://github.com/facebook/react-native/issues/19: 0x0000000185ad6c1c UIKitCore`_UIApplicationFlushCATransaction + 48 frame https://github.com/facebook/react-native/issues/20: 0x0000000185a07ccc UIKitCore`__setupUpdateSequence_block_invoke_2 + 352 frame https://github.com/facebook/react-native/issues/21: 0x000000018505d28c UIKitCore`_UIUpdateSequenceRun + 76 frame https://github.com/facebook/react-native/issues/22: 0x0000000185a07670 UIKitCore`schedulerStepScheduledMainSection + 168 frame https://github.com/facebook/react-native/issues/23: 0x0000000185a06aa8 UIKitCore`runloopSourceCallback + 80 frame https://github.com/facebook/react-native/issues/24: 0x000000018041b7c4 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24 frame https://github.com/facebook/react-native/issues/25: 0x000000018041b70c CoreFoundation`__CFRunLoopDoSource0 + 172 frame https://github.com/facebook/react-native/issues/26: 0x000000018041ae70 CoreFoundation`__CFRunLoopDoSources0 + 232 frame https://github.com/facebook/react-native/issues/27: 0x00000001804153b4 CoreFoundation`__CFRunLoopRun + 788 frame https://github.com/facebook/react-native/issues/28: 0x0000000180414c24 CoreFoundation`CFRunLoopRunSpecific + 552 frame https://github.com/facebook/react-native/issues/29: 0x000000019020ab10 GraphicsServices`GSEventRunModal + 160 frame https://github.com/facebook/react-native/issues/30: 0x0000000185ad82fc UIKitCore`-[UIApplication _run] + 796 frame https://github.com/facebook/react-native/issues/31: 0x0000000185adc4f4 UIKitCore`UIApplicationMain + 124 frame https://github.com/facebook/react-native/issues/32: 0x0000000104521f68 RNTester.debug.dylib`main(argc=1, argv=0x000000016b9f5af8) at main.m:15:12 frame https://github.com/facebook/react-native/issues/33: 0x00000001045b9410 dyld_sim`start_sim + 20 frame https://github.com/facebook/react-native/issues/34: 0x0000000104796274 dyld`start + 2840 ``` ## Changelog: [IOS] [FIXED] - Fabric: Fixes crash of dynamic color when light/dark mode changed Pull Request resolved: https://github.com/facebook/react-native/pull/48496 Test Plan: RNTester -> PlatformColor example -> changed the dark/light mode in the system settings -> go back to App and pop and push the PlatformColor example, it would crash:  Reviewed By: sammy-SC Differential Revision: D68157559 Pulled By: cipolleschi fbshipit-source-id: 01959845b742ce748186d3877b2792f0f9132ff5
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ff2e40371e
commit
cbaff1c7aa
+8
-5
@@ -24,8 +24,12 @@ struct Color {
|
||||
Color(int32_t color);
|
||||
Color(const DynamicColor& dynamicColor);
|
||||
Color(const ColorComponents& components);
|
||||
Color(std::shared_ptr<void> uiColor);
|
||||
Color() : uiColor_(nullptr){};
|
||||
int32_t getColor() const;
|
||||
int32_t getUIColorHash() const;
|
||||
|
||||
static Color createSemanticColor(std::vector<std::string>& semanticItems);
|
||||
|
||||
std::shared_ptr<void> getUIColor() const {
|
||||
return uiColor_;
|
||||
}
|
||||
@@ -48,6 +52,7 @@ struct Color {
|
||||
}
|
||||
|
||||
private:
|
||||
Color(std::shared_ptr<void> uiColor);
|
||||
std::shared_ptr<void> uiColor_;
|
||||
};
|
||||
|
||||
@@ -59,7 +64,7 @@ namespace HostPlatformColor {
|
||||
#define NO_DESTROY
|
||||
#endif
|
||||
|
||||
NO_DESTROY static const facebook::react::Color UndefinedColor = Color(nullptr);
|
||||
NO_DESTROY static const facebook::react::Color UndefinedColor = Color();
|
||||
} // namespace HostPlatformColor
|
||||
|
||||
inline Color
|
||||
@@ -103,8 +108,6 @@ inline float blueFromHostPlatformColor(Color color) {
|
||||
template <>
|
||||
struct std::hash<facebook::react::Color> {
|
||||
size_t operator()(const facebook::react::Color& color) const {
|
||||
auto seed = size_t{0};
|
||||
facebook::react::hash_combine(seed, color.getColor());
|
||||
return seed;
|
||||
return color.getUIColorHash();
|
||||
}
|
||||
};
|
||||
|
||||
+111
-15
@@ -6,9 +6,11 @@
|
||||
*/
|
||||
|
||||
#import "HostPlatformColor.h"
|
||||
#import "UIColor+Graphics.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <react/renderer/graphics/RCTPlatformColorUtils.h>
|
||||
#import <react/utils/ManagedObjectWrapper.h>
|
||||
#import <string>
|
||||
|
||||
@@ -19,13 +21,31 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
namespace facebook::react {
|
||||
|
||||
namespace {
|
||||
|
||||
bool UIColorIsP3ColorSpace(const std::shared_ptr<void> &uiColor)
|
||||
{
|
||||
UIColor *color = unwrapManagedObject(uiColor);
|
||||
CGColorSpaceRef colorSpace = CGColorGetColorSpace(color.CGColor);
|
||||
|
||||
if (CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelRGB) {
|
||||
CFStringRef name = CGColorSpaceGetName(colorSpace);
|
||||
if (name != NULL && CFEqual(name, kCGColorSpaceDisplayP3)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UIColor *_Nullable UIColorFromInt32(int32_t intColor)
|
||||
{
|
||||
CGFloat a = CGFloat((intColor >> 24) & 0xFF) / 255.0;
|
||||
CGFloat r = CGFloat((intColor >> 16) & 0xFF) / 255.0;
|
||||
CGFloat g = CGFloat((intColor >> 8) & 0xFF) / 255.0;
|
||||
CGFloat b = CGFloat(intColor & 0xFF) / 255.0;
|
||||
return [UIColor colorWithRed:r green:g blue:b alpha:a];
|
||||
|
||||
UIColor *color = [UIColor colorWithRed:r green:g blue:b alpha:a];
|
||||
color.reactHash = facebook::react::hash_combine(intColor, 0);
|
||||
return color;
|
||||
}
|
||||
|
||||
UIColor *_Nullable UIColorFromDynamicColor(const facebook::react::DynamicColor &dynamicColor)
|
||||
@@ -56,6 +76,7 @@ UIColor *_Nullable UIColorFromDynamicColor(const facebook::react::DynamicColor &
|
||||
}
|
||||
}
|
||||
}];
|
||||
color.reactHash = facebook::react::hash_combine(dark, light, highContrastDark, highContrastLight, 0);
|
||||
return color;
|
||||
} else {
|
||||
return nil;
|
||||
@@ -64,37 +85,95 @@ UIColor *_Nullable UIColorFromDynamicColor(const facebook::react::DynamicColor &
|
||||
return nil;
|
||||
}
|
||||
|
||||
int32_t ColorFromUIColor(UIColor *color)
|
||||
int32_t ColorFromColorComponents(const facebook::react::ColorComponents &components)
|
||||
{
|
||||
float ratio = 255;
|
||||
CGFloat rgba[4];
|
||||
[color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]];
|
||||
return ((int32_t)round((float)rgba[3] * ratio) & 0xff) << 24 | ((int)round((float)rgba[0] * ratio) & 0xff) << 16 |
|
||||
((int)round((float)rgba[1] * ratio) & 0xff) << 8 | ((int)round((float)rgba[2] * ratio) & 0xff);
|
||||
auto color = ((int32_t)round((float)components.alpha * ratio) & 0xff) << 24 |
|
||||
((int)round((float)components.red * ratio) & 0xff) << 16 |
|
||||
((int)round((float)components.green * ratio) & 0xff) << 8 | ((int)round((float)components.blue * ratio) & 0xff);
|
||||
return color;
|
||||
}
|
||||
|
||||
int32_t ColorFromUIColor(const std::shared_ptr<void> &uiColor)
|
||||
int32_t ColorFromUIColor(UIColor *color)
|
||||
{
|
||||
CGFloat rgba[4];
|
||||
[color getRed:&rgba[0] green:&rgba[1] blue:&rgba[2] alpha:&rgba[3]];
|
||||
return ColorFromColorComponents({(float)rgba[0], (float)rgba[1], (float)rgba[2], (float)rgba[3]});
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
UIColor *uiColor = nil;
|
||||
if (components.colorSpace == ColorSpace::DisplayP3) {
|
||||
return [UIColor colorWithDisplayP3Red:components.red
|
||||
green:components.green
|
||||
blue:components.blue
|
||||
alpha:components.alpha];
|
||||
uiColor = [UIColor colorWithDisplayP3Red:components.red
|
||||
green:components.green
|
||||
blue:components.blue
|
||||
alpha:components.alpha];
|
||||
} else {
|
||||
uiColor = [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha];
|
||||
}
|
||||
return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha];
|
||||
|
||||
auto color = ColorFromColorComponents(components);
|
||||
uiColor.reactHash = facebook::react::hash_combine(color, components.colorSpace == ColorSpace::DisplayP3);
|
||||
|
||||
return uiColor;
|
||||
}
|
||||
|
||||
int32_t hashFromUIColor(const std::shared_ptr<void> &uiColor)
|
||||
{
|
||||
if (uiColor == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
return facebook::react::hash_combine(
|
||||
darkColor,
|
||||
lightColor,
|
||||
darkAccessibilityContrastColor,
|
||||
lightAccessibilityContrastColor,
|
||||
UIColorIsP3ColorSpace(uiColor));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
Color::Color(int32_t color)
|
||||
@@ -114,6 +193,11 @@ Color::Color(const ColorComponents &components)
|
||||
|
||||
Color::Color(std::shared_ptr<void> uiColor)
|
||||
{
|
||||
UIColor *color = ((UIColor *)unwrapManagedObject(uiColor));
|
||||
if (color && color.reactHash == 0) {
|
||||
auto colorHash = hashFromUIColor(uiColor);
|
||||
color.reactHash = colorHash;
|
||||
}
|
||||
uiColor_ = std::move(uiColor);
|
||||
}
|
||||
|
||||
@@ -121,7 +205,8 @@ bool Color::operator==(const Color &other) const
|
||||
{
|
||||
return (!uiColor_ && !other.uiColor_) ||
|
||||
(uiColor_ && other.uiColor_ &&
|
||||
[unwrapManagedObject(getUIColor()) isEqual:unwrapManagedObject(other.getUIColor())]);
|
||||
((UIColor *)unwrapManagedObject(getUIColor())).reactHash ==
|
||||
((UIColor *)unwrapManagedObject(other.getUIColor())).reactHash);
|
||||
}
|
||||
|
||||
bool Color::operator!=(const Color &other) const
|
||||
@@ -142,6 +227,17 @@ float Color::getChannel(int channelId) const
|
||||
return static_cast<float>(rgba[channelId]);
|
||||
}
|
||||
|
||||
int32_t Color::getUIColorHash() const
|
||||
{
|
||||
return [(UIColor *)unwrapManagedObject(uiColor_) reactHash];
|
||||
}
|
||||
|
||||
Color Color::createSemanticColor(std::vector<std::string> &semanticItems)
|
||||
{
|
||||
auto semanticColor = RCTPlatformColorFromSemanticItems(semanticItems);
|
||||
return Color(wrapManagedObject(semanticColor));
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ SharedColor parsePlatformColor(const ContextContainer &contextContainer, int32_t
|
||||
auto items = (std::unordered_map<std::string, RawValue>)value;
|
||||
if (items.find("semantic") != items.end() && items.at("semantic").hasType<std::vector<std::string>>()) {
|
||||
auto semanticItems = (std::vector<std::string>)items.at("semantic");
|
||||
return {wrapManagedObject(RCTPlatformColorFromSemanticItems(semanticItems))};
|
||||
return SharedColor(Color::createSemanticColor(semanticItems));
|
||||
} else if (
|
||||
items.find("dynamic") != items.end() &&
|
||||
items.at("dynamic").hasType<std::unordered_map<std::string, RawValue>>()) {
|
||||
|
||||
+7
-1
@@ -8,9 +8,15 @@
|
||||
#pragma once
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <react/renderer/graphics/HostPlatformColor.h>
|
||||
#import <vector>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
struct ColorComponents;
|
||||
struct Color;
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
||||
facebook::react::ColorComponents RCTPlatformColorComponentsFromSemanticItems(
|
||||
std::vector<std::string>& semanticItems);
|
||||
UIColor* RCTPlatformColorFromSemanticItems(
|
||||
|
||||
+1
@@ -9,6 +9,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <react/renderer/graphics/HostPlatformColor.h>
|
||||
#import <react/utils/ManagedObjectWrapper.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface UIColor (Graphics)
|
||||
@property (nonatomic, assign) int32_t reactHash;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import "UIColor+Graphics.h"
|
||||
|
||||
@implementation UIColor (Graphics)
|
||||
|
||||
- (int32_t)reactHash
|
||||
{
|
||||
return [objc_getAssociatedObject(self, _cmd) intValue];
|
||||
}
|
||||
|
||||
- (void)setReactHash:(int32_t)reactHash
|
||||
{
|
||||
objc_setAssociatedObject(self, @selector(reactHash), @(reactHash), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user