Add accessibilityIdentifier to UITabBarItem
| Originator: | gcombs | ||
| Number: | rdar://15000843 | Date Originated: | 16-Sep-2013 01:17 PM |
| Status: | Open | Resolved: | |
| Product: | iOS SDK | Product Version: | 6.1 |
| Classification: | Enhancement | Reproducible: | Always |
Summary:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAccessibilityIdentification_Protocol/Introduction/Introduction.html
The UIAccessibilityIdentification Protocol reference indicates that we should use accessibilityIdentifier instead of accessibilityLabel for the purposes of UIAutomation. This makes perfect sense, given that an accessibilityLabel should be localized and an accessibilityIdentifier can be constant.
"An identifier can be used to uniquely identify an element in the scripts you write using the UI Automation interfaces. Using an identifier allows you to avoid inappropriately setting or accessing an element’s accessibility label."
However, neither UITabBarItem nor UIBarButtonItem conforms to the UIAccessibilityIdentification protocol.
If I subclass UITabBarItem in order to implement UIAccessibilityIdentification, and subsequently set an accessibilityIdentifier, it certainly doesn't get applied to the instance of the underlying internal class UITabBarButton. It seems that the only possible solution (aside from rolling our own tab bar from scratch) is to implement a subclass of UITabBar and override the accessibilityElementAtIndex: method -- injecting the appropriate accessibilityIdentifiers at runtime. To me, this seems like a silly, fragile, and hackish way to solve a simple problem.
I've attached an example implementation of the hack, to illustrate the problem. It's not a real workaround because it can't be shipped with production code (accessing properties of the private UITabBarButton class) and it doesn't actually set the properties until the user taps the tab item the first time. Until then it uses the accessibilityLabel.
Therefore, please add accessibilityIdentifier support to UITabBarItems.
Steps to Reproduce:
Expected Results:
UITabBarItem (or one of it's super classes) should implement UIAccessibilityIdentification Protocol. Setting the accessibilityIdentifier on a UITabBarItem instance should actually apply to the underlying (private) UITabBarButton so that UIAutomation recognizes the identifier.
Actual Results:
UITabBarItem (nor any of it's super classes) actually implement UIAccessibilityIdentification Protocol, and the only way to make it work (sort of) is a silly hack that can't go into production code.
Version:
iOS 7 GM SDK (also tried iOS 6.1 SDK)
Configuration:
Attachments:
'AccessibilityIDForTabBarItems.m'
@interface TapTabBarItem : UITabBarItem<UIAccessibilityIdentification>
@end
@implementation TapTabBarItem
@synthesize accessibilityIdentifier = _accessibilityIdentifier;
@end
@interface TapTabBar : UITabBar
@end
@implementation TapTabBar
#warning Obviously this is a crazy hack and cannot go into production builds due to private UITabBarButton
- (id)accessibilityElementAtIndex:(NSInteger)index {
id element = [super accessibilityElementAtIndex:index];
if (element && ![element accessibilityIdentifier]) {
@try {
// Unsuitable for production; UITabBarButton is Apple Private
NSString *title = [element valueForKeyPath:@"label.text"];
NSString *accessibilityIdentifier = [self accessibilityIdentifierForItemTitle:title];
[element setAccessibilityIdentifier:accessibilityIdentifier];
}
@catch (NSException *exception) {
}
}
return element;
}
- (NSInteger)indexOfAccessibilityElement:(id)element {
NSInteger index = [super indexOfAccessibilityElement:element];
if (element && ![element accessibilityIdentifier]) {
@try {
// Unsuitable for production; UITabBarButton is Apple Private
NSString *title = [element valueForKeyPath:@"label.text"];
NSString *accessibilityIdentifier = [self accessibilityIdentifierForItemTitle:title];
[element setAccessibilityIdentifier:accessibilityIdentifier];
}
@catch (NSException *exception) {
}
}
return index;
}
- (NSString *)accessibilityIdentifierForItemTitle:(NSString *)title {
if (!title || ![title isKindOfClass:[NSString class]] || ![title length]) {
return nil;
}
for (TapTabBarItem *item in self.items) {
if (item.tag == -1 || !item.title || ![item.title isEqualToString:title]) {
continue;
}
return item.accessibilityIdentifier;
}
return nil;
}
@end
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!