diff --git a/AsyncDisplayKit/ASDisplayNode.h b/AsyncDisplayKit/ASDisplayNode.h index 83ff98bc26..0318ab588b 100644 --- a/AsyncDisplayKit/ASDisplayNode.h +++ b/AsyncDisplayKit/ASDisplayNode.h @@ -695,6 +695,10 @@ NS_ASSUME_NONNULL_END - (nullable UIView *)preferredFocusedView; #endif +@end + +@interface ASDisplayNode (UIViewBridgeAccessibility) + // Accessibility support @property (atomic, assign) BOOL isAccessibilityElement; @property (nullable, atomic, copy) NSString *accessibilityLabel; diff --git a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm index ee6722623f..9c3b692da7 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+UIViewBridge.mm @@ -709,147 +709,173 @@ if (shouldApply) { _layer.layerProperty = (layerValueExpr); } else { ASDisplayNo _setToLayer(edgeAntialiasingMask, edgeAntialiasingMask); } +@end + + +#pragma mark - UIViewBridgeAccessibility + +// ASDK supports accessibility for view or layer backed nodes. To be able to provide support for layer backed +// nodes, properties for all of the UIAccessibility protocol defined properties need to be provided an held in sync +// between node and view + +// 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 +// - 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 )\ +: ASDisplayNodeGetPendingState(self).viewAndPendingViewStateProperty + +// Helper function to set property values on pending state or view and property if loaded +#define _setAccessibilityToViewAndProperty(nodeProperty, nodeValueExpr, viewAndPendingViewStateProperty, viewAndPendingViewStateExpr) \ +nodeProperty = nodeValueExpr; _setToViewOnly(viewAndPendingViewStateProperty, viewAndPendingViewStateExpr) + +@implementation ASDisplayNode (UIViewBridgeAccessibility) + - (BOOL)isAccessibilityElement { _bridge_prologue_read; - return _getFromViewOnly(isAccessibilityElement); + return _getAccessibilityFromViewOrProperty(_isAccessibilityElement, isAccessibilityElement); } - (void)setIsAccessibilityElement:(BOOL)isAccessibilityElement { _bridge_prologue_write; - _setToViewOnly(isAccessibilityElement, isAccessibilityElement); + _setAccessibilityToViewAndProperty(_isAccessibilityElement, isAccessibilityElement, isAccessibilityElement, isAccessibilityElement); } - (NSString *)accessibilityLabel { _bridge_prologue_read; - return _getFromViewOnly(accessibilityLabel); + return _getAccessibilityFromViewOrProperty(_accessibilityLabel, accessibilityLabel); } - (void)setAccessibilityLabel:(NSString *)accessibilityLabel { _bridge_prologue_write; - _setToViewOnly(accessibilityLabel, accessibilityLabel); + _setAccessibilityToViewAndProperty(_accessibilityLabel, accessibilityLabel, accessibilityLabel, accessibilityLabel); } - (NSString *)accessibilityHint { _bridge_prologue_read; - return _getFromViewOnly(accessibilityHint); + return _getAccessibilityFromViewOrProperty(_accessibilityHint, accessibilityHint); } - (void)setAccessibilityHint:(NSString *)accessibilityHint { _bridge_prologue_write; - _setToViewOnly(accessibilityHint, accessibilityHint); + _setAccessibilityToViewAndProperty(_accessibilityHint, accessibilityHint, accessibilityHint, accessibilityHint); } - (NSString *)accessibilityValue { _bridge_prologue_read; - return _getFromViewOnly(accessibilityValue); + return _getAccessibilityFromViewOrProperty(_accessibilityValue, accessibilityValue); } - (void)setAccessibilityValue:(NSString *)accessibilityValue { _bridge_prologue_write; - _setToViewOnly(accessibilityValue, accessibilityValue); + _setAccessibilityToViewAndProperty(_accessibilityValue, accessibilityValue, accessibilityValue, accessibilityValue); } - (UIAccessibilityTraits)accessibilityTraits { _bridge_prologue_read; - return _getFromViewOnly(accessibilityTraits); + return _getAccessibilityFromViewOrProperty(_accessibilityTraits, accessibilityTraits); } - (void)setAccessibilityTraits:(UIAccessibilityTraits)accessibilityTraits { _bridge_prologue_write; - _setToViewOnly(accessibilityTraits, accessibilityTraits); + _setAccessibilityToViewAndProperty(_accessibilityTraits, accessibilityTraits, accessibilityTraits, accessibilityTraits); } - (CGRect)accessibilityFrame { _bridge_prologue_read; - return _getFromViewOnly(accessibilityFrame); + return _getAccessibilityFromViewOrProperty(_accessibilityFrame, accessibilityFrame); } - (void)setAccessibilityFrame:(CGRect)accessibilityFrame { _bridge_prologue_write; - _setToViewOnly(accessibilityFrame, accessibilityFrame); + _setAccessibilityToViewAndProperty(_accessibilityFrame, accessibilityFrame, accessibilityFrame, accessibilityFrame); } - (NSString *)accessibilityLanguage { _bridge_prologue_read; - return _getFromViewOnly(accessibilityLanguage); + return _getAccessibilityFromViewOrProperty(_accessibilityLanguage, accessibilityLanguage); } - (void)setAccessibilityLanguage:(NSString *)accessibilityLanguage { _bridge_prologue_write; - _setToViewOnly(accessibilityLanguage, accessibilityLanguage); + _setAccessibilityToViewAndProperty(_accessibilityLanguage, accessibilityLanguage, accessibilityLanguage, accessibilityLanguage); } - (BOOL)accessibilityElementsHidden { _bridge_prologue_read; - return _getFromViewOnly(accessibilityElementsHidden); + return _getAccessibilityFromViewOrProperty(_accessibilityElementsHidden, accessibilityElementsHidden); } - (void)setAccessibilityElementsHidden:(BOOL)accessibilityElementsHidden { _bridge_prologue_write; - _setToViewOnly(accessibilityElementsHidden, accessibilityElementsHidden); + _setAccessibilityToViewAndProperty(_accessibilityElementsHidden, accessibilityElementsHidden, accessibilityElementsHidden, accessibilityElementsHidden); } - (BOOL)accessibilityViewIsModal { _bridge_prologue_read; - return _getFromViewOnly(accessibilityViewIsModal); + return _getAccessibilityFromViewOrProperty(_accessibilityViewIsModal, accessibilityViewIsModal); } - (void)setAccessibilityViewIsModal:(BOOL)accessibilityViewIsModal { _bridge_prologue_write; - _setToViewOnly(accessibilityViewIsModal, accessibilityViewIsModal); + _setAccessibilityToViewAndProperty(_accessibilityViewIsModal, accessibilityViewIsModal, accessibilityViewIsModal, accessibilityViewIsModal); } - (BOOL)shouldGroupAccessibilityChildren { _bridge_prologue_read; - return _getFromViewOnly(shouldGroupAccessibilityChildren); + return _getAccessibilityFromViewOrProperty(_shouldGroupAccessibilityChildren, shouldGroupAccessibilityChildren); } - (void)setShouldGroupAccessibilityChildren:(BOOL)shouldGroupAccessibilityChildren { _bridge_prologue_write; - _setToViewOnly(shouldGroupAccessibilityChildren, shouldGroupAccessibilityChildren); + _setAccessibilityToViewAndProperty(_shouldGroupAccessibilityChildren, shouldGroupAccessibilityChildren, shouldGroupAccessibilityChildren, shouldGroupAccessibilityChildren); } - (NSString *)accessibilityIdentifier { _bridge_prologue_read; - return _getFromViewOnly(accessibilityIdentifier); + return _getAccessibilityFromViewOrProperty(_accessibilityIdentifier, accessibilityIdentifier); } - (void)setAccessibilityIdentifier:(NSString *)accessibilityIdentifier { _bridge_prologue_write; - _setToViewOnly(accessibilityIdentifier, accessibilityIdentifier); + _setAccessibilityToViewAndProperty(_accessibilityIdentifier, accessibilityIdentifier, accessibilityIdentifier, accessibilityIdentifier); } - (NSInteger)accessibilityElementCount { - _bridge_prologue_read; - return _getFromViewOnly(accessibilityElementCount); + _bridge_prologue_read; + return _getFromViewOnly(accessibilityElementCount); } @end +#pragma mark - ASAsyncTransactionContainer + @implementation ASDisplayNode (ASAsyncTransactionContainer) - (BOOL)asyncdisplaykit_isAsyncTransactionContainer diff --git a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h index e8930b9865..641288087d 100644 --- a/AsyncDisplayKit/Private/ASDisplayNodeInternal.h +++ b/AsyncDisplayKit/Private/ASDisplayNodeInternal.h @@ -129,6 +129,19 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo ASDisplayNodeContextModifier _willDisplayNodeContentWithRenderingContext; ASDisplayNodeContextModifier _didDisplayNodeContentWithRenderingContext; + // Accessibility support + BOOL _isAccessibilityElement; + NSString *_accessibilityLabel; + NSString *_accessibilityHint; + NSString *_accessibilityValue; + UIAccessibilityTraits _accessibilityTraits; + CGRect _accessibilityFrame; + NSString *_accessibilityLanguage; + BOOL _accessibilityElementsHidden; + BOOL _accessibilityViewIsModal; + BOOL _shouldGroupAccessibilityChildren; + NSString *_accessibilityIdentifier; + #if TIME_DISPLAYNODE_OPS @public NSTimeInterval _debugTimeToCreateView;