From be2cabc3f89b22aa8624c476e48598274ca5dd75 Mon Sep 17 00:00:00 2001 From: Vladislav Alexeev Date: Tue, 14 Jul 2015 03:12:15 -0700 Subject: [PATCH] Dynamic Text Sizes for Text component Summary: Dynamic Text Sizes for Text component. Text gains new prop - allowFontScaling (true by default). There is also AccessibilityManager module that allows you to tune multipliers per each content size category, but predefined multipliers are there. This could potentially break some apps so please test carefully. --- Examples/UIExplorer/TextExample.ios.js | 19 ++++ Libraries/ART/RCTConvert+ART.m | 2 +- Libraries/Text/RCTShadowRawText.m | 24 ++++ Libraries/Text/RCTShadowText.h | 2 + Libraries/Text/RCTShadowText.m | 49 +++++++- Libraries/Text/RCTTextManager.m | 3 + Libraries/Text/Text.js | 17 ++- React/Base/RCTConvert.h | 3 +- React/Base/RCTConvert.m | 15 ++- React/Modules/RCTAccessibilityManager.h | 27 +++++ React/Modules/RCTAccessibilityManager.m | 144 ++++++++++++++++++++++++ React/Modules/RCTUIManager.h | 6 + React/Modules/RCTUIManager.m | 26 +++++ React/React.xcodeproj/project.pbxproj | 6 + 14 files changed, 331 insertions(+), 12 deletions(-) create mode 100644 React/Modules/RCTAccessibilityManager.h create mode 100644 React/Modules/RCTAccessibilityManager.m diff --git a/Examples/UIExplorer/TextExample.ios.js b/Examples/UIExplorer/TextExample.ios.js index 4aff00e73fa..cbc3e5b4194 100644 --- a/Examples/UIExplorer/TextExample.ios.js +++ b/Examples/UIExplorer/TextExample.ios.js @@ -369,6 +369,25 @@ exports.examples = [ ); }, +}, { + title: 'allowFontScaling attribute', + render: function() { + return ( + + + By default, text will respect Text Size accessibility setting on iOS. + It means that all font sizes will be increased or descreased depending on the value of Text Size setting in + {" "}Settings.app - Display & Brightness - Text Size + + + You can disable scaling for your Text component by passing {"\""}allowFontScaling={"{"}false{"}\""} prop. + + + This text will not scale. + + + ); + }, }]; var styles = StyleSheet.create({ diff --git a/Libraries/ART/RCTConvert+ART.m b/Libraries/ART/RCTConvert+ART.m index 7a607a12c23..e6bc092863d 100644 --- a/Libraries/ART/RCTConvert+ART.m +++ b/Libraries/ART/RCTConvert+ART.m @@ -87,7 +87,7 @@ RCT_ENUM_CONVERTER(CTTextAlignment, (@{ } NSDictionary *fontDict = dict[@"font"]; - CTFontRef font = (__bridge CTFontRef)[self UIFont:nil withFamily:fontDict[@"fontFamily"] size:fontDict[@"fontSize"] weight:fontDict[@"fontWeight"] style:fontDict[@"fontStyle"]]; + CTFontRef font = (__bridge CTFontRef)[self UIFont:nil withFamily:fontDict[@"fontFamily"] size:fontDict[@"fontSize"] weight:fontDict[@"fontWeight"] style:fontDict[@"fontStyle"] scaleMultiplier:1.0]; if (!font) { return frame; } diff --git a/Libraries/Text/RCTShadowRawText.m b/Libraries/Text/RCTShadowRawText.m index 00a3490bcf2..4f79d64b58a 100644 --- a/Libraries/Text/RCTShadowRawText.m +++ b/Libraries/Text/RCTShadowRawText.m @@ -9,8 +9,32 @@ #import "RCTShadowRawText.h" +#import "RCTUIManager.h" + @implementation RCTShadowRawText +- (instancetype)init +{ + if ((self = [super init])) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(contentSizeMultiplierDidChange:) + name:RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification + object:nil]; + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)contentSizeMultiplierDidChange:(NSNotification *)note +{ + [self dirtyLayout]; + [self dirtyText]; +} + - (void)setText:(NSString *)text { if (_text != text) { diff --git a/Libraries/Text/RCTShadowText.h b/Libraries/Text/RCTShadowText.h index fe87e99c122..abb11187969 100644 --- a/Libraries/Text/RCTShadowText.h +++ b/Libraries/Text/RCTShadowText.h @@ -30,6 +30,8 @@ extern NSString *const RCTReactTagAttributeName; @property (nonatomic, strong) UIColor *textDecorationColor; @property (nonatomic, assign) NSUnderlineStyle textDecorationStyle; @property (nonatomic, assign) RCTTextDecorationLineType textDecorationLine; +@property (nonatomic, assign) CGFloat fontSizeMultiplier; +@property (nonatomic, assign) BOOL allowFontScaling; - (void)recomputeText; diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index 621df1ed618..adcca5aed33 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -9,6 +9,9 @@ #import "RCTShadowText.h" +#import "RCTAccessibilityManager.h" +#import "RCTUIManager.h" +#import "RCTBridge.h" #import "RCTConvert.h" #import "RCTLog.h" #import "RCTShadowRawText.h" @@ -51,16 +54,31 @@ static css_dim_t RCTMeasure(void *context, float width) _letterSpacing = NAN; _isHighlighted = NO; _textDecorationStyle = NSUnderlineStyleSingle; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(contentSizeMultiplierDidChange:) + name:RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification + object:nil]; } return self; } +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + - (NSString *)description { NSString *superDescription = super.description; return [[superDescription substringToIndex:superDescription.length - 1] stringByAppendingFormat:@"; text: %@>", [self attributedString].string]; } +- (void)contentSizeMultiplierDidChange:(NSNotification *)note +{ + [self dirtyLayout]; + [self dirtyText]; +} + - (NSDictionary *)processUpdatedProperties:(NSMutableSet *)applierBlocks parentProperties:(NSDictionary *)parentProperties { @@ -190,7 +208,9 @@ static css_dim_t RCTMeasure(void *context, float width) [self _addAttribute:NSBackgroundColorAttributeName withValue:self.backgroundColor toAttributedString:attributedString]; } - UIFont *font = [RCTConvert UIFont:nil withFamily:fontFamily size:fontSize weight:fontWeight style:fontStyle]; + UIFont *font = [RCTConvert UIFont:nil withFamily:fontFamily + size:fontSize weight:fontWeight style:fontStyle + scaleMultiplier:(_allowFontScaling && _fontSizeMultiplier > 0.0 ? _fontSizeMultiplier : 1.0)]; [self _addAttribute:NSFontAttributeName withValue:font toAttributedString:attributedString]; [self _addAttribute:NSKernAttributeName withValue:letterSpacing toAttributedString:attributedString]; [self _addAttribute:RCTReactTagAttributeName withValue:self.reactTag toAttributedString:attributedString]; @@ -247,8 +267,9 @@ static css_dim_t RCTMeasure(void *context, float width) NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.alignment = _textAlign; paragraphStyle.baseWritingDirection = _writingDirection; - paragraphStyle.minimumLineHeight = _lineHeight; - paragraphStyle.maximumLineHeight = _lineHeight; + CGFloat lineHeight = round(_lineHeight * self.fontSizeMultiplier); + paragraphStyle.minimumLineHeight = lineHeight; + paragraphStyle.maximumLineHeight = lineHeight; [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:(NSRange){0, attributedString.length}]; @@ -321,4 +342,26 @@ RCT_TEXT_PROPERTY(TextDecorationLine, _textDecorationLine, RCTTextDecorationLine RCT_TEXT_PROPERTY(TextDecorationStyle, _textDecorationStyle, NSUnderlineStyle); RCT_TEXT_PROPERTY(WritingDirection, _writingDirection, NSWritingDirection) +- (void)setAllowFontScaling:(BOOL)allowFontScaling +{ + _allowFontScaling = allowFontScaling; + for (RCTShadowView *child in [self reactSubviews]) { + if ([child isKindOfClass:[RCTShadowText class]]) { + [(RCTShadowText *)child setAllowFontScaling:allowFontScaling]; + } + } + [self dirtyText]; +} + +- (void)setFontSizeMultiplier:(CGFloat)fontSizeMultiplier +{ + _fontSizeMultiplier = fontSizeMultiplier; + for (RCTShadowView *child in [self reactSubviews]) { + if ([child isKindOfClass:[RCTShadowText class]]) { + [(RCTShadowText *)child setFontSizeMultiplier:fontSizeMultiplier]; + } + } + [self dirtyText]; +} + @end diff --git a/Libraries/Text/RCTTextManager.m b/Libraries/Text/RCTTextManager.m index b5f959b73e9..06d52088ab4 100644 --- a/Libraries/Text/RCTTextManager.m +++ b/Libraries/Text/RCTTextManager.m @@ -9,6 +9,7 @@ #import "RCTTextManager.h" +#import "RCTAccessibilityManager.h" #import "RCTAssert.h" #import "RCTConvert.h" #import "RCTLog.h" @@ -49,6 +50,7 @@ RCT_EXPORT_SHADOW_PROPERTY(textDecorationStyle, NSUnderlineStyle) RCT_EXPORT_SHADOW_PROPERTY(textDecorationColor, UIColor) RCT_EXPORT_SHADOW_PROPERTY(textDecorationLine, RCTTextDecorationLineType) RCT_EXPORT_SHADOW_PROPERTY(writingDirection, NSWritingDirection) +RCT_EXPORT_SHADOW_PROPERTY(allowFontScaling, BOOL) - (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(RCTSparseArray *)shadowViewRegistry { @@ -69,6 +71,7 @@ RCT_EXPORT_SHADOW_PROPERTY(writingDirection, NSWritingDirection) RCTAssert([shadowView isTextDirty], @"Don't process any nodes that don't have dirty text"); if ([shadowView isKindOfClass:[RCTShadowText class]]) { + [(RCTShadowText *)shadowView setFontSizeMultiplier:self.bridge.accessibilityManager.multiplier]; [(RCTShadowText *)shadowView recomputeText]; } else if ([shadowView isKindOfClass:[RCTShadowRawText class]]) { RCTLogError(@"Raw text cannot be used outside of a tag. Not rendering string: '%@'", diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index d02733749be..7b370ac3999 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -30,6 +30,7 @@ var viewConfig = { validAttributes: merge(ReactNativeViewAttributes.UIView, { isHighlighted: true, numberOfLines: true, + allowFontScaling: true, }), uiViewClassName: 'RCTText', }; @@ -99,16 +100,27 @@ var Text = React.createClass({ * * {nativeEvent: {layout: {x, y, width, height}}}. */ - onLayout: React.PropTypes.func, + onLayout: React.PropTypes.func, + /** + * Specifies should fonts scale to respect Text Size accessibility setting. + */ + allowFontScaling: React.PropTypes.bool, }, viewConfig: viewConfig, - getInitialState: function() { + getInitialState: function(): Object { return merge(this.touchableGetInitialState(), { isHighlighted: false, }); }, + + getDefaultProps: function(): Object { + return { + numberOfLines: 0, + allowFontScaling: true, + }; + }, onStartShouldSetResponder: function(): bool { var shouldSetFromProps = this.props.onStartShouldSetResponder && @@ -231,6 +243,7 @@ if (Platform.OS === 'android') { RCTVirtualText = createReactNativeComponentClass({ validAttributes: merge(ReactNativeViewAttributes.UIView, { isHighlighted: true, + allowFontScaling: false, }), uiViewClassName: 'RCTVirtualText', }); diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index 1b010accdf0..d4657ec7451 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -91,7 +91,8 @@ typedef NSURL RCTFileURL; + (UIFont *)UIFont:(UIFont *)font withStyle:(id)json; + (UIFont *)UIFont:(UIFont *)font withFamily:(id)json; + (UIFont *)UIFont:(UIFont *)font withFamily:(id)family - size:(id)size weight:(id)weight style:(id)style; + size:(id)size weight:(id)weight style:(id)style + scaleMultiplier:(CGFloat)scaleMultiplier; typedef NSArray NSStringArray; + (NSStringArray *)NSStringArray:(id)json; diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 06e0805468c..2305a12171f 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -779,31 +779,33 @@ static BOOL RCTFontIsCondensed(UIFont *font) withFamily:json[@"fontFamily"] size:json[@"fontSize"] weight:json[@"fontWeight"] - style:json[@"fontStyle"]]; + style:json[@"fontStyle"] + scaleMultiplier:1.0f]; } + (UIFont *)UIFont:(UIFont *)font withSize:(id)json { - return [self UIFont:font withFamily:nil size:json weight:nil style:nil]; + return [self UIFont:font withFamily:nil size:json weight:nil style:nil scaleMultiplier:1.0]; } + (UIFont *)UIFont:(UIFont *)font withWeight:(id)json { - return [self UIFont:font withFamily:nil size:nil weight:json style:nil]; + return [self UIFont:font withFamily:nil size:nil weight:json style:nil scaleMultiplier:1.0]; } + (UIFont *)UIFont:(UIFont *)font withStyle:(id)json { - return [self UIFont:font withFamily:nil size:nil weight:nil style:json]; + return [self UIFont:font withFamily:nil size:nil weight:nil style:json scaleMultiplier:1.0]; } + (UIFont *)UIFont:(UIFont *)font withFamily:(id)json { - return [self UIFont:font withFamily:json size:nil weight:nil style:nil]; + return [self UIFont:font withFamily:json size:nil weight:nil style:nil scaleMultiplier:1.0]; } + (UIFont *)UIFont:(UIFont *)font withFamily:(id)family size:(id)size weight:(id)weight style:(id)style + scaleMultiplier:(CGFloat)scaleMultiplier { // Defaults NSString *const RCTDefaultFontFamily = @"System"; @@ -828,6 +830,9 @@ static BOOL RCTFontIsCondensed(UIFont *font) // Get font attributes fontSize = [self CGFloat:size] ?: fontSize; + if (scaleMultiplier > 0.0 && scaleMultiplier != 1.0) { + fontSize = round(fontSize * scaleMultiplier); + } familyName = [self NSString:family] ?: familyName; isItalic = style ? [self RCTFontStyle:style] : isItalic; fontWeight = weight ? [self RCTFontWeight:weight] : fontWeight; diff --git a/React/Modules/RCTAccessibilityManager.h b/React/Modules/RCTAccessibilityManager.h new file mode 100644 index 00000000000..03d22f9456e --- /dev/null +++ b/React/Modules/RCTAccessibilityManager.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import "RCTBridgeModule.h" +#import "RCTBridge.h" + +extern NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification; // posted when multiplier is changed + +@interface RCTAccessibilityManager : NSObject + +@property (nonatomic, readonly) CGFloat multiplier; + +@end + +@interface RCTBridge (RCTAccessibilityManager) + +@property (nonatomic, readonly) RCTAccessibilityManager *accessibilityManager; + +@end diff --git a/React/Modules/RCTAccessibilityManager.m b/React/Modules/RCTAccessibilityManager.m new file mode 100644 index 00000000000..9271b1e3d72 --- /dev/null +++ b/React/Modules/RCTAccessibilityManager.m @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "RCTAccessibilityManager.h" + +#import "RCTLog.h" + +NSString *const RCTAccessibilityManagerDidUpdateMultiplierNotification = @"RCTAccessibilityManagerDidUpdateMultiplierNotification"; + +@interface RCTAccessibilityManager () + +@property (nonatomic, copy) NSDictionary *multipliers; +@property (nonatomic, copy) NSString *contentSizeCategory; +@property (nonatomic, assign) CGFloat multiplier; + +@end + +@implementation RCTAccessibilityManager + +@synthesize bridge = _bridge; + +RCT_EXPORT_MODULE() + ++ (NSDictionary *)JSToUIKitMap +{ + static NSDictionary *map = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + map = @{@"extraSmall": UIContentSizeCategoryExtraSmall, + @"small": UIContentSizeCategorySmall, + @"medium": UIContentSizeCategoryMedium, + @"large": UIContentSizeCategoryLarge, + @"extraLarge": UIContentSizeCategoryExtraLarge, + @"extraExtraLarge": UIContentSizeCategoryExtraExtraLarge, + @"extraExtraExtraLarge": UIContentSizeCategoryExtraExtraExtraLarge, + @"accessibilityMedium": UIContentSizeCategoryAccessibilityMedium, + @"accessibilityLarge": UIContentSizeCategoryAccessibilityLarge, + @"accessibilityExtraLarge": UIContentSizeCategoryAccessibilityExtraLarge, + @"accessibilityExtraExtraLarge": UIContentSizeCategoryAccessibilityExtraExtraLarge, + @"accessibilityExtraExtraExtraLarge": UIContentSizeCategoryAccessibilityExtraExtraExtraLarge}; + }); + return map; +} + ++ (NSString *)UIKitCategoryFromJSCategory:(NSString *)JSCategory +{ + return self.JSToUIKitMap[JSCategory]; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didReceiveNewContentSizeCategory:) + name:UIContentSizeCategoryDidChangeNotification + object:[UIApplication sharedApplication]]; + self.contentSizeCategory = [[UIApplication sharedApplication] preferredContentSizeCategory]; + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)didReceiveNewContentSizeCategory:(NSNotification *)note +{ + self.contentSizeCategory = note.userInfo[UIContentSizeCategoryNewValueKey]; +} + +- (void)setContentSizeCategory:(NSString *)contentSizeCategory +{ + if (_contentSizeCategory != contentSizeCategory) { + _contentSizeCategory = [contentSizeCategory copy]; + self.multiplier = [self multiplierForContentSizeCategory:_contentSizeCategory]; + [[NSNotificationCenter defaultCenter] postNotificationName:RCTAccessibilityManagerDidUpdateMultiplierNotification object:self]; + } +} + +- (CGFloat)multiplierForContentSizeCategory:(NSString *)category +{ + NSNumber *m = self.multipliers[category]; + if (m.doubleValue <= 0.0) { + RCTLogError(@"Can't determinte multiplier for category %@. Using 1.0.", category); + m = @1.0; + } + return m.doubleValue; +} + +- (NSDictionary *)multipliers +{ + if (_multipliers == nil) { + _multipliers = @{UIContentSizeCategoryExtraSmall: @0.823, + UIContentSizeCategorySmall: @0.882, + UIContentSizeCategoryMedium: @0.941, + UIContentSizeCategoryLarge: @1.0, + UIContentSizeCategoryExtraLarge: @1.118, + UIContentSizeCategoryExtraExtraLarge: @1.235, + UIContentSizeCategoryExtraExtraExtraLarge: @1.353, + UIContentSizeCategoryAccessibilityMedium: @1.786, + UIContentSizeCategoryAccessibilityLarge: @2.143, + UIContentSizeCategoryAccessibilityExtraLarge: @2.643, + UIContentSizeCategoryAccessibilityExtraExtraLarge: @3.143, + UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @3.571}; + } + return _multipliers; +} + +RCT_EXPORT_METHOD(setAccessibilityContentSizeMultipliers:(NSDictionary *)JSMultipliers) +{ + NSMutableDictionary *multipliers = [[NSMutableDictionary alloc] init]; + for (NSString *__nonnull JSCategory in JSMultipliers) { + NSNumber *m = JSMultipliers[JSCategory]; + NSString *UIKitCategory = [self.class UIKitCategoryFromJSCategory:JSCategory]; + multipliers[UIKitCategory] = m; + } + self.multipliers = multipliers; +} + +RCT_EXPORT_METHOD(getMultiplier:(RCTResponseSenderBlock)callback) +{ + if (callback) { + callback(@[ @(self.multiplier) ]); + } +} + +@end + +@implementation RCTBridge (RCTAccessibilityManager) + +- (RCTAccessibilityManager *)accessibilityManager +{ + return self.modules[RCTBridgeModuleNameForClass([RCTAccessibilityManager class])]; +} + +@end diff --git a/React/Modules/RCTUIManager.h b/React/Modules/RCTUIManager.h index cbd7c167f63..1efedc51051 100644 --- a/React/Modules/RCTUIManager.h +++ b/React/Modules/RCTUIManager.h @@ -14,6 +14,12 @@ #import "RCTInvalidating.h" #import "RCTViewManager.h" +/** + * Posted right before re-render happens. This is a chance for views to invalidate their state so + * next render cycle will pick up updated views and layout appropriately. + */ +extern NSString *const RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification; + @protocol RCTScrollableProtocol; /** diff --git a/React/Modules/RCTUIManager.m b/React/Modules/RCTUIManager.m index f526f5f8ca3..39cd38a213f 100644 --- a/React/Modules/RCTUIManager.m +++ b/React/Modules/RCTUIManager.m @@ -14,6 +14,7 @@ #import #import "Layout.h" +#import "RCTAccessibilityManager.h" #import "RCTAnimationType.h" #import "RCTAssert.h" #import "RCTBridge.h" @@ -35,6 +36,8 @@ static void RCTTraverseViewNodes(id view, void (^block)(id)); static NSDictionary *RCTPropsMerge(NSDictionary *beforeProps, NSDictionary *newProps); +NSString *const RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification = @"RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification"; + @interface RCTAnimation : NSObject @property (nonatomic, readonly) NSTimeInterval duration; @@ -262,10 +265,33 @@ static NSDictionary *RCTViewConfigForModule(Class managerClass) _rootViewTags = [[NSMutableSet alloc] init]; _bridgeTransactionListeners = [[NSMutableSet alloc] init]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didReceiveNewContentSizeMultiplier) + name:RCTAccessibilityManagerDidUpdateMultiplierNotification + object:nil]; } return self; } +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)didReceiveNewContentSizeMultiplier +{ + __weak RCTUIManager *weakSelf = self; + dispatch_async(self.methodQueue, ^{ + __weak RCTUIManager *strongSelf = weakSelf; + if (strongSelf) { + [[NSNotificationCenter defaultCenter] postNotificationName:RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification + object:strongSelf]; + [strongSelf batchDidComplete]; + } + }); +} + - (BOOL)isValid { return _viewRegistry != nil; diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index 5e0434b3014..d0bbda232cc 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ 83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */; }; 83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */; }; 83CBBACC1A6023D300E9B192 /* RCTConvert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBACB1A6023D300E9B192 /* RCTConvert.m */; }; + E9B20B7B1B500126007A2DA7 /* RCTAccessibilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -239,6 +240,8 @@ 83CBBACA1A6023D300E9B192 /* RCTConvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTConvert.h; sourceTree = ""; }; 83CBBACB1A6023D300E9B192 /* RCTConvert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert.m; sourceTree = ""; }; E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTTextDecorationLineType.h; sourceTree = ""; }; + E9B20B791B500126007A2DA7 /* RCTAccessibilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAccessibilityManager.h; sourceTree = ""; }; + E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAccessibilityManager.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -275,6 +278,8 @@ 13B07FE01A69315300A75B9A /* Modules */ = { isa = PBXGroup; children = ( + E9B20B791B500126007A2DA7 /* RCTAccessibilityManager.h */, + E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */, 13B07FE71A69327A00A75B9A /* RCTAlertManager.h */, 13B07FE81A69327A00A75B9A /* RCTAlertManager.m */, 1372B7081AB030C200659ED6 /* RCTAppState.h */, @@ -567,6 +572,7 @@ 137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */, 13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */, 13B080051A6947C200A75B9A /* RCTScrollView.m in Sources */, + E9B20B7B1B500126007A2DA7 /* RCTAccessibilityManager.m in Sources */, 13B07FF21A69327A00A75B9A /* RCTTiming.m in Sources */, 1372B70A1AB030C200659ED6 /* RCTAppState.m in Sources */, 134FCB3D1A6E7F0800051CC8 /* RCTContextExecutor.m in Sources */,