mirror of
https://github.com/HackPlan/AsyncDisplayKit.git
synced 2026-03-28 23:58:50 +08:00
Merge remote-tracking branch 'facebook/master' into 500pxgram
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = 'AsyncDisplayKit'
|
||||
spec.version = '1.9.8'
|
||||
spec.version = '1.9.7.2'
|
||||
spec.license = { :type => 'BSD' }
|
||||
spec.homepage = 'http://asyncdisplaykit.org'
|
||||
spec.authors = { 'Scott Goodson' => 'scottgoodson@gmail.com', 'Ryan Nystrom' => 'rnystrom@fb.com' }
|
||||
spec.summary = 'Smooth asynchronous user interfaces for iOS apps.'
|
||||
spec.source = { :git => 'https://github.com/facebook/AsyncDisplayKit.git', :tag => '1.9.7.1' }
|
||||
spec.source = { :git => 'https://github.com/facebook/AsyncDisplayKit.git', :tag => '1.9.7.2' }
|
||||
|
||||
spec.documentation_url = 'http://asyncdisplaykit.org/appledoc/'
|
||||
|
||||
|
||||
@@ -2451,6 +2451,141 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DB1020801CBCA2AD00FA6FE1 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_CODE_COVERAGE = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_GENERATE_TEST_COVERAGE_FILES = YES;
|
||||
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
DB1020811CBCA2AD00FA6FE1 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = YES;
|
||||
CLANG_ENABLE_CODE_COVERAGE = YES;
|
||||
DSTROOT = /tmp/AsyncDisplayKit.dst;
|
||||
GCC_INPUT_FILETYPE = automatic;
|
||||
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch";
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
|
||||
OTHER_CFLAGS = "-Wall";
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PUBLIC_HEADERS_FOLDER_PATH = "include/$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
DB1020821CBCA2AD00FA6FE1 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D3779BCFF841AD3EB56537ED /* Pods-AsyncDisplayKitTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CLANG_ENABLE_CODE_COVERAGE = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"COCOAPODS=1",
|
||||
"FB_REFERENCE_IMAGE_DIR=\"\\\"$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages\\\"\"",
|
||||
);
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
|
||||
INFOPLIST_FILE = "AsyncDisplayKitTests/AsyncDisplayKitTests-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AsyncDisplayKitTestHost.app/AsyncDisplayKitTestHost";
|
||||
WRAPPER_EXTENSION = xctest;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
DB1020831CBCA2AD00FA6FE1 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO;
|
||||
INFOPLIST_FILE = AsyncDisplayKitTestHost/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
DB1020841CBCA2AD00FA6FE1 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_CODE_COVERAGE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREFIX_HEADER = "AsyncDisplayKit/AsyncDisplayKit-Prefix.pch";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/AsyncDisplayKit-iOS/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MODULEMAP_FILE = AsyncDisplayKit/module.modulemap;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = AsyncDisplayKit;
|
||||
SKIP_INSTALL = YES;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@@ -2459,6 +2594,7 @@
|
||||
buildConfigurations = (
|
||||
057D02DF1AC0A66800C7AC3C /* Debug */,
|
||||
057D02E01AC0A66800C7AC3C /* Release */,
|
||||
DB1020831CBCA2AD00FA6FE1 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
@@ -2468,6 +2604,7 @@
|
||||
buildConfigurations = (
|
||||
058D09CD195D04C000B7D73C /* Debug */,
|
||||
058D09CE195D04C000B7D73C /* Release */,
|
||||
DB1020801CBCA2AD00FA6FE1 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
@@ -2477,6 +2614,7 @@
|
||||
buildConfigurations = (
|
||||
058D09D0195D04C000B7D73C /* Debug */,
|
||||
058D09D1195D04C000B7D73C /* Release */,
|
||||
DB1020811CBCA2AD00FA6FE1 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
@@ -2486,6 +2624,7 @@
|
||||
buildConfigurations = (
|
||||
058D09D3195D04C000B7D73C /* Debug */,
|
||||
058D09D4195D04C000B7D73C /* Release */,
|
||||
DB1020821CBCA2AD00FA6FE1 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
@@ -2495,6 +2634,7 @@
|
||||
buildConfigurations = (
|
||||
B35061EE1B010EDF0018CF92 /* Debug */,
|
||||
B35061EF1B010EDF0018CF92 /* Release */,
|
||||
DB1020841CBCA2AD00FA6FE1 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
|
||||
@@ -755,8 +755,13 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_scheduleCheckForBatchFetching
|
||||
- (void)_scheduleCheckForBatchFetchingForNumberOfChanges:(NSUInteger)changes
|
||||
{
|
||||
// Prevent fetching will continually trigger in a loop after reaching end of content and no new content was provided
|
||||
if (changes == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Push this to the next runloop to be sure the scroll view has the right content size
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _checkForBatchFetching];
|
||||
@@ -973,6 +978,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes
|
||||
}
|
||||
|
||||
NSUInteger numberOfUpdateBlocks = _batchUpdateBlocks.count;
|
||||
ASPerformBlockWithoutAnimation(!animated, ^{
|
||||
[_layoutFacilitator collectionViewWillPerformBatchUpdates];
|
||||
[super performBatchUpdates:^{
|
||||
@@ -980,7 +986,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
block();
|
||||
}
|
||||
} completion:^(BOOL finished){
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:numberOfUpdateBlocks];
|
||||
if (completion) { completion(finished); }
|
||||
}];
|
||||
});
|
||||
@@ -1005,7 +1011,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditCellsAtIndexPaths:indexPaths batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super insertItemsAtIndexPaths:indexPaths];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexPaths.count];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -1026,7 +1032,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditCellsAtIndexPaths:indexPaths batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super deleteItemsAtIndexPaths:indexPaths];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexPaths.count];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -1047,7 +1053,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditSectionsAtIndexSet:indexSet batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super insertSections:indexSet];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexSet.count];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -1068,7 +1074,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
[_layoutFacilitator collectionViewWillEditSectionsAtIndexSet:indexSet batched:NO];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[super deleteSections:indexSet];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexSet.count];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2695,7 +2695,7 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
|
||||
|
||||
- (BOOL)supportsUpwardPropagation
|
||||
{
|
||||
return YES;
|
||||
return ASEnvironmentStatePropagationEnabled();
|
||||
}
|
||||
|
||||
ASEnvironmentLayoutOptionsForwarding
|
||||
|
||||
@@ -730,8 +730,13 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_scheduleCheckForBatchFetching
|
||||
- (void)_scheduleCheckForBatchFetchingForNumberOfChanges:(NSUInteger)changes
|
||||
{
|
||||
// Prevent fetching will continually trigger in a loop after reaching end of content and no new content was provided
|
||||
if (changes == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Push this to the next runloop to be sure the scroll view has the right content size
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self _checkForBatchFetching];
|
||||
@@ -904,7 +909,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexPaths.count];
|
||||
});
|
||||
|
||||
if (_automaticallyAdjustsContentOffset) {
|
||||
@@ -924,7 +929,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexPaths.count];
|
||||
});
|
||||
|
||||
if (_automaticallyAdjustsContentOffset) {
|
||||
@@ -945,7 +950,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexSet.count];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -961,7 +966,7 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
[super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetching];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexSet.count];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
__unsafe_unretained ASDisplayNode *_node; // Though UIView has a .node property added via category, since we can add an ivar to a subclass, use that for performance.
|
||||
BOOL _inHitTest;
|
||||
BOOL _inPointInside;
|
||||
NSMutableArray *_accessibleElements;
|
||||
NSArray *_accessibleElements;
|
||||
}
|
||||
|
||||
@synthesize asyncdisplaykit_node = _node;
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
#import "ASDisplayNodeExtras.h"
|
||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
|
||||
#pragma mark - UIAccessibilityElement
|
||||
|
||||
@implementation UIAccessibilityElement (_ASDisplayView)
|
||||
@@ -34,10 +31,27 @@
|
||||
|
||||
#pragma mark - _ASDisplayView / UIAccessibilityContainer
|
||||
|
||||
@interface _ASDisplayView () {
|
||||
NSMutableArray *_accessibleElements;
|
||||
static NSArray *ASCollectUIAccessibilityElementsForNode(ASDisplayNode *viewNode, ASDisplayNode *subnode, id container) {
|
||||
NSMutableArray *accessibleElements = [NSMutableArray array];
|
||||
ASDisplayNodePerformBlockOnEveryNodeBFS(subnode, ^(ASDisplayNode * _Nonnull currentNode) {
|
||||
// For every subnode that is layer backed or it's supernode has shouldRasterizeDescendants enabled
|
||||
// we have to create a UIAccessibilityElement as no view for this node exists
|
||||
if (currentNode != viewNode && currentNode.isAccessibilityElement) {
|
||||
UIAccessibilityElement *accessibilityElement = [UIAccessibilityElement accessibilityElementWithContainer:container node:currentNode];
|
||||
// As the node hierarchy is flattened it's necessary to convert the frame for each subnode in the tree to the
|
||||
// coordinate system of the supernode
|
||||
CGRect frame = [viewNode convertRect:currentNode.bounds fromNode:currentNode];
|
||||
accessibilityElement.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(frame, container);
|
||||
[accessibleElements addObject:accessibilityElement];
|
||||
}
|
||||
});
|
||||
|
||||
return [accessibleElements copy];
|
||||
}
|
||||
|
||||
@interface _ASDisplayView () {
|
||||
NSArray *_accessibleElements;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation _ASDisplayView (UIAccessibilityContainer)
|
||||
@@ -46,51 +60,41 @@
|
||||
|
||||
- (NSArray *)accessibleElements
|
||||
{
|
||||
ASDisplayNode *selfNode = self.asyncdisplaykit_node;
|
||||
if (selfNode == nil) {
|
||||
ASDisplayNode *viewNode = self.asyncdisplaykit_node;
|
||||
if (viewNode == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_accessibleElements = [[NSMutableArray alloc] init];
|
||||
|
||||
// Handle rasterize case
|
||||
if (selfNode.shouldRasterizeDescendants) {
|
||||
// If the node has shouldRasterizeDescendants enabled it's necessaty to go through the whole subnodes
|
||||
// tree of the node in BFS fashion and create for all subnodes UIAccessibilityElement objects ourselves
|
||||
// as the view hierarchy is flattened
|
||||
ASDisplayNodePerformBlockOnEveryNodeBFS(selfNode, ^(ASDisplayNode * _Nonnull node) {
|
||||
// For every subnode we have to create a UIAccessibilityElement as we cannot just add the view to the
|
||||
// accessibleElements as for a subnode of a node with shouldRasterizeDescendants enabled no view exists
|
||||
if (node != selfNode && node.isAccessibilityElement) {
|
||||
UIAccessibilityElement *accessibilityElement = [UIAccessibilityElement accessibilityElementWithContainer:self node:node];
|
||||
// As the node hierarchy is flattened it's necessary to convert the frame for each subnode in the tree to the
|
||||
// coordinate system of the node with shouldRasterizeDescendants enabled
|
||||
CGRect frame = [selfNode convertRect:node.bounds fromNode:node];
|
||||
accessibilityElement.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(frame, self);
|
||||
[_accessibleElements addObject:accessibilityElement];
|
||||
}
|
||||
});
|
||||
if (viewNode.shouldRasterizeDescendants) {
|
||||
_accessibleElements = ASCollectUIAccessibilityElementsForNode(viewNode, viewNode, self);
|
||||
return _accessibleElements;
|
||||
}
|
||||
|
||||
// Handle not rasterize case
|
||||
// Create UI accessiblity elements for each subnode that represent an elment within the accessibility container
|
||||
for (ASDisplayNode *subnode in selfNode.subnodes) {
|
||||
NSMutableArray *accessibleElements = [NSMutableArray array];
|
||||
|
||||
for (ASDisplayNode *subnode in viewNode.subnodes) {
|
||||
if (subnode.isAccessibilityElement) {
|
||||
// An accessiblityElement can either be a UIView or a UIAccessibilityElement
|
||||
id accessiblityElement = nil;
|
||||
if (subnode.isLayerBacked) {
|
||||
// The same comment for layer backed nodes is true as for subnodes within a shouldRasterizeDescendants node.
|
||||
// See details above
|
||||
// No view for layer backed nodes exist. It's necessary to create a UIAccessibilityElement that represents this node
|
||||
accessiblityElement = [UIAccessibilityElement accessibilityElementWithContainer:self node:subnode];
|
||||
} else {
|
||||
accessiblityElement = subnode.view;
|
||||
}
|
||||
[accessiblityElement setAccessibilityFrame:UIAccessibilityConvertFrameToScreenCoordinates(subnode.frame, self)];
|
||||
[_accessibleElements addObject:accessiblityElement];
|
||||
} else if ([subnode accessibilityElementCount] > 0) { // Check if it's an UIAccessibilityContainer
|
||||
[_accessibleElements addObject:subnode.view];
|
||||
[accessibleElements addObject:accessiblityElement];
|
||||
} else if (subnode.isLayerBacked) {
|
||||
// Go down the hierarchy of the layer backed subnode and collect all of the UIAccessibilityElement
|
||||
[accessibleElements addObjectsFromArray:ASCollectUIAccessibilityElementsForNode(viewNode, subnode, self)];
|
||||
} else if ([subnode accessibilityElementCount] > 0) {
|
||||
// Add UIAccessibilityContainer
|
||||
[accessibleElements addObject:subnode.view];
|
||||
}
|
||||
}
|
||||
_accessibleElements = [accessibleElements copy];
|
||||
|
||||
return _accessibleElements;
|
||||
}
|
||||
|
||||
@@ -81,8 +81,14 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
|
||||
|
||||
id<ASLayoutable> finalLayoutable = [child finalLayoutable];
|
||||
if (finalLayoutable != child) {
|
||||
// Layout options state of child needs to be copied to final layoutable, but don't override customized values.
|
||||
ASEnvironmentStatePropagateUp(finalLayoutable, child.environmentState.layoutOptionsState);
|
||||
if (ASEnvironmentStatePropagationEnabled()) {
|
||||
ASEnvironmentStatePropagateUp(finalLayoutable, child.environmentState.layoutOptionsState);
|
||||
} else {
|
||||
// If state propagation is not enabled the layout options state needs to be copied manually
|
||||
ASEnvironmentState finalLayoutableEnvironmentState = finalLayoutable.environmentState;
|
||||
finalLayoutableEnvironmentState.layoutOptionsState = child.environmentState.layoutOptionsState;
|
||||
finalLayoutable.environmentState = finalLayoutableEnvironmentState;
|
||||
}
|
||||
return finalLayoutable;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +175,7 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey";
|
||||
// the specifications that are known to have more than one.
|
||||
- (BOOL)supportsUpwardPropagation
|
||||
{
|
||||
return YES;
|
||||
return ASEnvironmentStatePropagationEnabled();
|
||||
}
|
||||
|
||||
ASEnvironmentLayoutOptionsForwarding
|
||||
|
||||
@@ -79,6 +79,9 @@ extern void ASLayoutableClearCurrentContext();
|
||||
#define ASEnvironmentLayoutOptionsForwarding \
|
||||
- (void)propagateUpLayoutOptionsState\
|
||||
{\
|
||||
if (!ASEnvironmentStatePropagationEnabled()) {\
|
||||
return;\
|
||||
}\
|
||||
id<ASEnvironment> parent = [self parent];\
|
||||
if ([parent supportsUpwardPropagation]) {\
|
||||
ASEnvironmentStatePropagateUp(parent, _environmentState.layoutOptionsState);\
|
||||
|
||||
@@ -721,7 +721,7 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { ASDisplayNo
|
||||
// Helper function with following logic:
|
||||
// - If the node is not loaded yet use the property from the pending state
|
||||
// - In case the node is loaded
|
||||
// - Check if the node has a view and get the
|
||||
// - Check if the node has a view and get the value from the view if loaded or from the pending state
|
||||
// - If view is not available, e.g. the node is layer backed return the property value
|
||||
#define _getAccessibilityFromViewOrProperty(nodeProperty, viewAndPendingViewStateProperty) __loaded(self) ? \
|
||||
(_view ? _view.viewAndPendingViewStateProperty : nodeProperty )\
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
enum class ASEnvironmentStatePropagation { DOWN, UP };
|
||||
BOOL ASEnvironmentStatePropagationEnabled();
|
||||
|
||||
|
||||
#pragma mark - Set and get extensible values for layout options
|
||||
@@ -33,6 +33,11 @@ void ASEnvironmentPerformBlockOnObjectAndChildren(id<ASEnvironment> object, void
|
||||
void ASEnvironmentPerformBlockOnObjectAndParents(id<ASEnvironment> object, void(^block)(id<ASEnvironment> object));
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
enum class ASEnvironmentStatePropagation { DOWN, UP };
|
||||
|
||||
|
||||
#pragma mark - Merging
|
||||
|
||||
static const struct ASEnvironmentStateExtensions ASEnvironmentDefaultStateExtensions = {};
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
|
||||
#define AS_SUPPORT_PROPAGATION NO
|
||||
|
||||
BOOL ASEnvironmentStatePropagationEnabled()
|
||||
{
|
||||
return AS_SUPPORT_PROPAGATION;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Traversing an ASEnvironment Tree
|
||||
|
||||
@@ -109,7 +114,7 @@ ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environme
|
||||
// Merge object and layout options state
|
||||
LOG(@"Merge object and state: %@ - ASEnvironmentLayoutOptionsState", object);
|
||||
|
||||
if (!AS_SUPPORT_PROPAGATION) {
|
||||
if (!ASEnvironmentStatePropagationEnabled()) {
|
||||
return environmentState;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user