Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added attributed versions of accessibilityLabel, accessibilityHint, accessibilityValue #554

Merged
merged 9 commits into from
Sep 18, 2017
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## master

* Add your own contributions to the next release on the line below this with your name.
- [ASDisplayNode] Add attributed versions of a11y label, hint and value. [#554](https://github.com/TextureGroup/Texture/pull/554) [Alexander Hüllmandel](https://github.com/fruitcoder)
- [ASCollectionNode] Add -isProcessingUpdates and -onDidFinishProcessingUpdates: APIs. [#522](https://github.com/TextureGroup/Texture/pull/522) [Scott Goodson](https://github.com/appleguy)
- [Accessibility] Add .isAccessibilityContainer property, allowing automatic aggregation of children's a11y labels. [#468][Scott Goodson](https://github.com/appleguy)
- [ASImageNode] Enabled .clipsToBounds by default, fixing the use of .cornerRadius and clipping of GIFs. [Scott Goodson](https://github.com/appleguy) [#466](https://github.com/TextureGroup/Texture/pull/466)
Expand Down
3 changes: 3 additions & 0 deletions Source/ASDisplayNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,11 @@ extern NSInteger const ASDefaultDrawingPriority;
// Accessibility support
@property (nonatomic, assign) BOOL isAccessibilityElement;
@property (nonatomic, copy, nullable) NSString *accessibilityLabel;
@property (nonatomic, copy, nullable) NSAttributedString *accessibilityAttributedLabel API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, copy, nullable) NSString *accessibilityHint;
@property (nonatomic, copy, nullable) NSAttributedString *accessibilityAttributedHint API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, copy, nullable) NSString *accessibilityValue;
@property (nonatomic, copy, nullable) NSAttributedString *accessibilityAttributedValue API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, assign) UIAccessibilityTraits accessibilityTraits;
@property (nonatomic, assign) CGRect accessibilityFrame;
@property (nonatomic, copy, nullable) UIBezierPath *accessibilityPath;
Expand Down
11 changes: 7 additions & 4 deletions Source/Details/UIView+ASConvenience.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,15 @@ NS_ASSUME_NONNULL_BEGIN
as they are already on NSObject

@property (nonatomic, assign) BOOL isAccessibilityElement;
@property (nonatomic, copy) NSString *accessibilityLabel;
@property (nonatomic, copy) NSString *accessibilityHint;
@property (nonatomic, copy) NSString *accessibilityValue;
@property (nonatomic, copy, nullable) NSString *accessibilityLabel;
@property (nonatomic, copy, nullable) NSAttributedString *accessibilityAttributedLabel API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, copy, nullable) NSString *accessibilityHint;
@property (nonatomic, copy, nullable) NSAttributedString *accessibilityAttributedHint API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, copy, nullable) NSString *accessibilityValue;
@property (nonatomic, copy, nullable) NSAttributedString *accessibilityAttributedValue API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, assign) UIAccessibilityTraits accessibilityTraits;
@property (nonatomic, assign) CGRect accessibilityFrame;
@property (nonatomic, strong) NSString *accessibilityLanguage;
@property (nonatomic, strong, nullable) NSString *accessibilityLanguage;
@property (nonatomic, assign) BOOL accessibilityElementsHidden;
@property (nonatomic, assign) BOOL accessibilityViewIsModal;
@property (nonatomic, assign) BOOL shouldGroupAccessibilityChildren;
Expand Down
23 changes: 21 additions & 2 deletions Source/Details/_ASDisplayViewAccessiblity.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#ifndef ASDK_ACCESSIBILITY_DISABLE

#import <AsyncDisplayKit/_ASDisplayView.h>
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
Expand Down Expand Up @@ -83,6 +84,11 @@ + (ASAccessibilityElement *)accessibilityElementWithContainer:(UIView *)containe
accessibilityElement.accessibilityHint = node.accessibilityHint;
accessibilityElement.accessibilityValue = node.accessibilityValue;
accessibilityElement.accessibilityTraits = node.accessibilityTraits;
if (AS_AT_LEAST_IOS11) {
[accessibilityElement setValue:node.accessibilityAttributedLabel forKey:@"accessibilityAttributedLabel"];
[accessibilityElement setValue:node.accessibilityAttributedHint forKey:@"accessibilityAttributedHint"];
[accessibilityElement setValue:node.accessibilityAttributedValue forKey:@"accessibilityAttributedValue"];
}
return accessibilityElement;
}

Expand Down Expand Up @@ -169,8 +175,21 @@ static void CollectAccessibilityElementsForContainer(ASDisplayNode *container, _
}

SortAccessibilityElements(labeledNodes);
NSArray *labels = [labeledNodes valueForKey:@"accessibilityLabel"];
accessiblityElement.accessibilityLabel = [labels componentsJoinedByString:@", "];

if (AS_AT_LEAST_IOS11) {
NSArray *attributedLabels = [labeledNodes valueForKey:@"accessibilityAttributedLabel"];
NSMutableAttributedString *attributedLabel = [NSMutableAttributedString new];
[attributedLabels enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (idx != 0) {
[attributedLabel appendAttributedString:[[NSAttributedString alloc] initWithString:@", "]];
}
[attributedLabel appendAttributedString:(NSAttributedString *)obj];
}];
[accessiblityElement setValue:attributedLabel forKey:@"accessibilityAttributedLabel"];
} else {
NSArray *labels = [labeledNodes valueForKey:@"accessibilityLabel"];
accessiblityElement.accessibilityLabel = [labels componentsJoinedByString:@", "];
}

SortAccessibilityElements(actions);
accessiblityElement.accessibilityCustomActions = actions;
Expand Down
64 changes: 64 additions & 0 deletions Source/Private/ASDisplayNode+UIViewBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -873,10 +873,20 @@ - (void)setSemanticContentAttribute:(UISemanticContentAttribute)semanticContentA
(_view ? _view.viewAndPendingViewStateProperty : nodeProperty )\
: ASDisplayNodeGetPendingState(self).viewAndPendingViewStateProperty

// Attributed version of `_getAccessibilityFromViewOrProperty` macro
#define _getAttributedAccessibilityFromViewOrProperty(nodeProperty, viewAndPendingViewStatePropertyKey) __loaded(self) ? \
(_view ? (NSAttributedString *)[_view valueForKey: viewAndPendingViewStatePropertyKey] : nodeProperty )\
: (NSAttributedString *)[ASDisplayNodeGetPendingState(self) valueForKey: viewAndPendingViewStatePropertyKey]

// 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)

// Attributed version of `_setAccessibilityToViewAndProperty` macro
#define _setAttributedAccessibilityToViewAndProperty(nodeProperty, nodeValueExpr, viewAndPendingViewStatePropertyKey, viewAndPendingViewStateExpr) \
nodeProperty = nodeValueExpr; BOOL shouldApply = ASDisplayNodeShouldApplyBridgedWriteToView(self); \
if (shouldApply) { [_view setValue:(viewAndPendingViewStateExpr) forKey: viewAndPendingViewStatePropertyKey]; } else { [ASDisplayNodeGetPendingState(self) setValue:(viewAndPendingViewStateExpr) forKey:viewAndPendingViewStatePropertyKey]; }

@implementation ASDisplayNode (UIViewBridgeAccessibility)

- (BOOL)isAccessibilityElement
Expand All @@ -901,6 +911,28 @@ - (void)setAccessibilityLabel:(NSString *)accessibilityLabel
{
_bridge_prologue_write;
_setAccessibilityToViewAndProperty(_accessibilityLabel, accessibilityLabel, accessibilityLabel, accessibilityLabel);
if (AS_AT_LEAST_IOS11) {
_accessibilityAttributedLabel = [[NSAttributedString alloc] initWithString:accessibilityLabel];
BOOL shouldApply = ASDisplayNodeShouldApplyBridgedWriteToView(self);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use _setAttributedAccessibilityToViewAndProperty here?

if (shouldApply) {
[_view setValue: [[NSAttributedString alloc] initWithString:accessibilityLabel] forKey:@"accessibilityAttributedLabel"];
} else {
[ASDisplayNodeGetPendingState(self) setValue: [[NSAttributedString alloc] initWithString:accessibilityLabel] forKey:@"accessibilityAttributedLabel"];
}
}
}

- (NSAttributedString *)accessibilityAttributedLabel
{
_bridge_prologue_read;
return _getAttributedAccessibilityFromViewOrProperty(_accessibilityAttributedLabel, @"accessibilityAttributedLabel");
}

- (void)setAccessibilityAttributedLabel:(NSAttributedString *)accessibilityAttributedLabel
{
_bridge_prologue_write;
{ _setAttributedAccessibilityToViewAndProperty(_accessibilityAttributedLabel, accessibilityAttributedLabel, @"accessibilityAttributedLabel", accessibilityAttributedLabel); }
{ _setAttributedAccessibilityToViewAndProperty(_accessibilityLabel, accessibilityAttributedLabel.string, @"accessibilityLabel", accessibilityAttributedLabel.string); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we use _setAccessibilityToViewAndProperty for _accessibilityLabel?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I wonder if one of the tests should have caught that. But you're definitely right!

}

- (NSString *)accessibilityHint
Expand All @@ -913,6 +945,22 @@ - (void)setAccessibilityHint:(NSString *)accessibilityHint
{
_bridge_prologue_write;
_setAccessibilityToViewAndProperty(_accessibilityHint, accessibilityHint, accessibilityHint, accessibilityHint);
if (AS_AT_LEAST_IOS11) {
_setAttributedAccessibilityToViewAndProperty(_accessibilityAttributedHint, [[NSAttributedString alloc] initWithString:accessibilityHint], @"accessibilityAttributedHint", [[NSAttributedString alloc] initWithString:accessibilityHint]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: For readability and a tiny perf win, cache [[NSAttributedString alloc] initWithString:accessibilityHint] instead of allocating 2 identical objects.

}
}

- (NSAttributedString *)accessibilityAttributedHint
{
_bridge_prologue_read;
return _getAttributedAccessibilityFromViewOrProperty(_accessibilityAttributedHint, @"accessibilityAttributedHint");
}

- (void)setAccessibilityAttributedHint:(NSAttributedString *)accessibilityAttributedHint
{
_bridge_prologue_write;
{ _setAttributedAccessibilityToViewAndProperty(_accessibilityAttributedHint, accessibilityAttributedHint, @"accessibilityAttributedHint", accessibilityAttributedHint); }
{ _setAttributedAccessibilityToViewAndProperty(_accessibilityHint, accessibilityAttributedHint.string, @"accessibilityHint", accessibilityAttributedHint.string); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, use _setAccessibilityToViewAndProperty for _accessibilityHint.

}

- (NSString *)accessibilityValue
Expand All @@ -925,6 +973,22 @@ - (void)setAccessibilityValue:(NSString *)accessibilityValue
{
_bridge_prologue_write;
_setAccessibilityToViewAndProperty(_accessibilityValue, accessibilityValue, accessibilityValue, accessibilityValue);
if (AS_AT_LEAST_IOS11) {
_setAttributedAccessibilityToViewAndProperty(_accessibilityAttributedValue, [[NSAttributedString alloc] initWithString:accessibilityValue], @"accessibilityAttributedValue", [[NSAttributedString alloc] initWithString:accessibilityValue]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Same here, cache the attributed string.

}
}

- (NSAttributedString *)accessibilityAttributedValue
{
_bridge_prologue_read;
return _getAttributedAccessibilityFromViewOrProperty(_accessibilityAttributedValue, @"accessibilityAttributedValue");
}

- (void)setAccessibilityAttributedValue:(NSAttributedString *)accessibilityAttributedValue
{
_bridge_prologue_write;
{ _setAttributedAccessibilityToViewAndProperty(_accessibilityAttributedValue, accessibilityAttributedValue, @"accessibilityAttributedValue", accessibilityAttributedValue); }
{ _setAttributedAccessibilityToViewAndProperty(_accessibilityValue, accessibilityAttributedValue.string, @"accessibilityValue", accessibilityAttributedValue.string); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use _setAccessibilityToViewAndProperty.

}

- (UIAccessibilityTraits)accessibilityTraits
Expand Down
3 changes: 3 additions & 0 deletions Source/Private/ASDisplayNodeInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,11 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
// Accessibility support
BOOL _isAccessibilityElement;
NSString *_accessibilityLabel;
NSAttributedString *_accessibilityAttributedLabel;
NSString *_accessibilityHint;
NSAttributedString *_accessibilityAttributedHint;
NSString *_accessibilityValue;
NSAttributedString *_accessibilityAttributedValue;
UIAccessibilityTraits _accessibilityTraits;
CGRect _accessibilityFrame;
NSString *_accessibilityLanguage;
Expand Down
93 changes: 87 additions & 6 deletions Source/Private/_ASPendingState.mm
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@
int setEdgeAntialiasingMask:1;
int setIsAccessibilityElement:1;
int setAccessibilityLabel:1;
int setAccessibilityAttributedLabel:1;
int setAccessibilityHint:1;
int setAccessibilityAttributedHint:1;
int setAccessibilityValue:1;
int setAccessibilityAttributedValue:1;
int setAccessibilityTraits:1;
int setAccessibilityFrame:1;
int setAccessibilityLanguage:1;
Expand Down Expand Up @@ -121,8 +124,11 @@ @implementation _ASPendingState
BOOL asyncTransactionContainer;
BOOL isAccessibilityElement;
NSString *accessibilityLabel;
NSAttributedString *accessibilityAttributedLabel;
NSString *accessibilityHint;
NSAttributedString *accessibilityAttributedHint;
NSString *accessibilityValue;
NSAttributedString *accessibilityAttributedValue;
UIAccessibilityTraits accessibilityTraits;
CGRect accessibilityFrame;
NSString *accessibilityLanguage;
Expand Down Expand Up @@ -271,8 +277,11 @@ - (instancetype)init
borderColor = blackColorRef;
isAccessibilityElement = NO;
accessibilityLabel = nil;
accessibilityAttributedLabel = nil;
accessibilityHint = nil;
accessibilityAttributedHint = nil;
accessibilityValue = nil;
accessibilityAttributedValue = nil;
accessibilityTraits = UIAccessibilityTraitNone;
accessibilityFrame = CGRectZero;
accessibilityLanguage = nil;
Expand Down Expand Up @@ -586,9 +595,26 @@ - (NSString *)accessibilityLabel

- (void)setAccessibilityLabel:(NSString *)newAccessibilityLabel
{
_flags.setAccessibilityLabel = YES;
if (accessibilityLabel != newAccessibilityLabel) {
if (![accessibilityLabel isEqualToString:newAccessibilityLabel]) {
_flags.setAccessibilityLabel = YES;
_flags.setAccessibilityAttributedLabel = YES;
accessibilityLabel = [newAccessibilityLabel copy];
accessibilityAttributedLabel = [[NSAttributedString alloc] initWithString:newAccessibilityLabel];
}
}

- (NSAttributedString *)accessibilityAttributedLabel
{
return accessibilityAttributedLabel;
}

- (void)setAccessibilityAttributedLabel:(NSAttributedString *)newAccessibilityAttributedLabel
{
if (![accessibilityAttributedLabel isEqualToAttributedString: newAccessibilityAttributedLabel]) {
_flags.setAccessibilityAttributedLabel = YES;
_flags.setAccessibilityLabel = YES;
accessibilityAttributedLabel = [newAccessibilityAttributedLabel copy];
accessibilityLabel = [newAccessibilityAttributedLabel.string copy];
}
}

Expand All @@ -599,8 +625,27 @@ - (NSString *)accessibilityHint

- (void)setAccessibilityHint:(NSString *)newAccessibilityHint
{
_flags.setAccessibilityHint = YES;
accessibilityHint = [newAccessibilityHint copy];
if (![accessibilityHint isEqualToString:newAccessibilityHint]) {
_flags.setAccessibilityHint = YES;
_flags.setAccessibilityAttributedHint = YES;
accessibilityHint = [newAccessibilityHint copy];
accessibilityAttributedHint = [[NSAttributedString alloc] initWithString:newAccessibilityHint];
}
}

- (NSAttributedString *)accessibilityAttributedHint
{
return accessibilityAttributedHint;
}

- (void)setAccessibilityAttributedHint:(NSAttributedString *)newAccessibilityAttributedHint
{
if (![accessibilityAttributedHint isEqual:newAccessibilityAttributedHint]) {
_flags.setAccessibilityAttributedHint = YES;
_flags.setAccessibilityHint = YES;
accessibilityAttributedHint = [newAccessibilityAttributedHint copy];
accessibilityHint = [newAccessibilityAttributedHint.string copy];
}
}

- (NSString *)accessibilityValue
Expand All @@ -610,8 +655,27 @@ - (NSString *)accessibilityValue

- (void)setAccessibilityValue:(NSString *)newAccessibilityValue
{
_flags.setAccessibilityValue = YES;
accessibilityValue = [newAccessibilityValue copy];
if (![accessibilityValue isEqualToString:newAccessibilityValue]) {
_flags.setAccessibilityValue = YES;
_flags.setAccessibilityAttributedValue = YES;
accessibilityValue = [newAccessibilityValue copy];
accessibilityAttributedValue = [[NSAttributedString alloc] initWithString:newAccessibilityValue];
}
}

- (NSAttributedString *)accessibilityAttributedValue
{
return accessibilityAttributedValue;
}

- (void)setAccessibilityAttributedValue:(NSAttributedString *)newAccessibilityAttributedValue
{
if (![accessibilityAttributedValue isEqualToAttributedString:newAccessibilityAttributedValue]) {
_flags.setAccessibilityAttributedValue = YES;
_flags.setAccessibilityValue = YES;
accessibilityAttributedValue = [newAccessibilityAttributedValue copy];
accessibilityValue = [newAccessibilityAttributedValue.string copy];
}
}

- (UIAccessibilityTraits)accessibilityTraits
Expand Down Expand Up @@ -994,12 +1058,21 @@ - (void)applyToView:(UIView *)view withSpecialPropertiesHandling:(BOOL)specialPr
if (flags.setAccessibilityLabel)
view.accessibilityLabel = accessibilityLabel;

if (AS_AT_LEAST_IOS11 && flags.setAccessibilityAttributedLabel)
[view setValue:accessibilityAttributedLabel forKey:@"accessibilityAttributedLabel"];

if (flags.setAccessibilityHint)
view.accessibilityHint = accessibilityHint;

if (AS_AT_LEAST_IOS11 && flags.setAccessibilityAttributedHint)
[view setValue:accessibilityAttributedHint forKey:@"accessibilityAttributedHint"];

if (flags.setAccessibilityValue)
view.accessibilityValue = accessibilityValue;

if (AS_AT_LEAST_IOS11 && flags.setAccessibilityAttributedValue)
[view setValue:accessibilityAttributedValue forKey:@"accessibilityAttributedValue"];

if (flags.setAccessibilityTraits)
view.accessibilityTraits = accessibilityTraits;

Expand Down Expand Up @@ -1142,6 +1215,11 @@ + (_ASPendingState *)pendingViewStateFromView:(UIView *)view
pendingState.accessibilityLabel = view.accessibilityLabel;
pendingState.accessibilityHint = view.accessibilityHint;
pendingState.accessibilityValue = view.accessibilityValue;
if (AS_AT_LEAST_IOS11) {
pendingState.accessibilityAttributedLabel = [view valueForKey: @"accessibilityAttributedLabel"];
pendingState.accessibilityAttributedHint = [view valueForKey: @"accessibilityAttributedHint"];
pendingState.accessibilityAttributedValue = [view valueForKey: @"accessibilityAttributedValue"];
}
pendingState.accessibilityTraits = view.accessibilityTraits;
pendingState.accessibilityFrame = view.accessibilityFrame;
pendingState.accessibilityLanguage = view.accessibilityLanguage;
Expand Down Expand Up @@ -1219,8 +1297,11 @@ - (BOOL)hasChanges
|| flags.setSemanticContentAttribute
|| flags.setIsAccessibilityElement
|| flags.setAccessibilityLabel
|| flags.setAccessibilityAttributedLabel
|| flags.setAccessibilityHint
|| flags.setAccessibilityAttributedHint
|| flags.setAccessibilityValue
|| flags.setAccessibilityAttributedValue
|| flags.setAccessibilityTraits
|| flags.setAccessibilityFrame
|| flags.setAccessibilityLanguage
Expand Down
Loading