I'm trying to access the value()
of a UIAStaticText
(a UILabel
in the objective C code) JavaScript object. I can set the value just fine using setValue()
and I can confirm that the simulator updates the text, but when I try to get the value I only get null
.
i.e.
text.setValue("new text");
updat开发者_如何学运维es the label to "new text" in the simulator.
text.value()
still returns null
after I've set the value.
What am I doing wrong here?
Looks like the root of the problem is in accessibilityValue
property of UILabel
returning accessibilityLabel
, not the UILabel
text as it should. To solve this problem I override accessibilityValue
property in my custom UILabel
category.
@interface UILabel (MyAccessibility)
@property(nonatomic, copy) NSString *accessibilityValue;
@end
@implementation UILabel (MyAccessibility)
@dynamic accessibilityValue;
-(NSString *)accessibilityValue {
// Here we force UIKit to return Label value, not the accessibility label
return self.text;
}
@end
Besides this minor trick, I always try to prefer accessibility Identifier over accessibility Label to prepare my UI elements for automated testing. Check out "Accessibility Label and Identifier Attributes" section of Instruments New Features User Guide.
After many hours of searching and trying things I found this on O'Reilly Answers confirming there is a bug where you cannot get a value for a static text label using Apple's UIAutomation framework. Here is the quote:
The text label string of a UILabel shows up as the StaticText field's name, not it's value, which is always nil. If you set the Accessibility label, it becomes the name property, and there is no longer any way to discover the current text in a UILabel. I have a bug report open with Apple about this.
Actually, it's not necessary to create the category specified by Viktor Krykun. Setting the accessibilityIdentifier is enough -- Apple's docs say (iOS 6.1.3):
Accessibility Label and Identifier Attributes
The identifier attribute allows you to use more descriptive names for elements. It is optional, but it must be set for the script to perform either of these two operations:
- Accessing a container view by name while also being able to access its children.
- Accessing a UILabel view by name to obtain its displayed text (via its value attribute).
It may also be necessary to explicitly set
uilabel.accessibilityLabel = NSLocalizedString(@"Element description", @"Localized accessibility label for VoiceOver");
uilabel.accessibilityValue = uilabel.text;
In my own code I have one case where it just works, and another one where I have to explicitly set the values. My best guess at the difference is that maybe it's because I entered and then deleted the accessibility label in Interface Builder in one case -- there may end up being a difference between nil and empty string or something. Apple's code is clearly kind of fragile here (SDK 6.1.3, testing on iOS 5.0 simulator).
In reply to ChrisH (since I don't see how reply to him): You could apply the same trick to UITableViewCell as to UILabel and then for a label's text inside a cell communicate with the cell for the value() instead of the static text in it. Although really it feels like piling more hacks on top of hacks. But I don't see any other way.
Edit: Added full implementation including the existing solution for completeness sake.
@interface UILabel (MyAccessibility)
@property(nonatomic, copy) NSString *accessibilityValue;
@end
@implementation UILabel (MyAccessibility)
@dynamic accessibilityValue;
-(NSString *)accessibilityValue {
// Here we force UIKit to return Label value, not the accessibility label
return self.text;
}
@end
@interface UITableViewCell (AccessibilityFix)
@property(nonatomic, copy) NSString *accessibilityValue;
@end
@implementation UITableViewCell (AccessibilityFix)
@dynamic accessibilityValue;
-(NSString *)accessibilityValue {
// Here we force UIKit to return Label value, not the accessibility label
return self.textLabel.text;
}
@end
精彩评论