On May 11, 2010, at 4:10 AM, Christiaan Hofman wrote: On May 11, 2010, at 2:17, James Dempsey wrote: On May 10, 2010, at 2:57 PM, Mickey Roberson wrote: I have implemented custom table cells (subclass of NSTextFieldCell) in my application (a Twitter client). Each cell represents a tweet including things like name, date, tweet text, etc. Within my cell subclass I have the following code:
- (NSArray *)accessibilityAttributeNames { if(validAXAttributes == nil) { validAXAttributes = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute, NSAccessibilityRoleDescriptionAttribute, NSAccessibilityHelpAttribute, NSAccessibilityFocusedAttribute, NSAccessibilityParentAttribute, NSAccessibilityChildrenAttribute, NSAccessibilityWindowAttribute, NSAccessibilityPositionAttribute, NSAccessibilitySizeAttribute, NSAccessibilityEnabledAttribute, NSAccessibilityValueAttribute, nil]; } return validAXAttributes; }
- (id)accessibilityAttributeValue:(NSString *)attribute { if([attribute isEqualToString:NSAccessibilityRoleAttribute]) //AXRole return NSAccessibilityStaticTextRole; if([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) //AXRoleDescription return @"Timeline Tweet"; if([attribute isEqualToString:NSAccessibilityHelpAttribute]) //AXHelp return @"Timeline Tweet"; if([attribute isEqualToString:NSAccessibilityValueAttribute]) { //AXValue SRXTweetObject* tweet = (SRXTweetObject*)[self objectValue]; NSMutableString* readableString = [NSMutableString stringWithFormat:@"%@: %@", [tweet.user displayName], tweet.text]; //Removed for brevity... return readableString; } return [super accessibilityAttributeValue:attribute]; }
Mickey - it's great that you are working towards making your app accessible! That's great!
You should always ignore NSAccessibilityException exceptions - and if you have special exception-handling code, you should always re-raise NSAccessibilityExceptions. They are expected to occur even if there is no problem in your application.
Why? For historic reasons, AppKit uses exceptions internally to deal with situations where an application needs to send an error back to the accessibility client.
So, you can and should safely ignore those exceptions.
Some other things to point out, scanning through the code you provided:
1. When subclassing a text field cell, it is best to let the NSAccessibilityValueAttribute keep its inherited behavior (which reports the string value of the text field). This is because there are a number of other attributes and parameterized attributes, such as AXNumberOfCharacters, AXBoundsForRange, AXAttributedStringForRange, AXStringForRange, etc, which all are based on the value of the text field.
Can anyone tell me precisely WHICH (parameterized) attributes the roles like AXStaticText and AXTextArea are supposed to implement and how they are supposed to be related? I can certainly not find it in the documentation (yes, I did read them).
Christiaan
The NSAccessibility protocol reference has a description of each parameterized attribute:
If this is not documented, or not documented well enough, please file a bug report at bugreporter.apple.com. This should be documented.
In the meantime, you can get what you need by launching TextEdit and using Accessibility Inspector on it. Lock focus on the text area, and the inspector will show you all the parameterized attributes it has - an AXTextArea should have those parameterized attribute. Then open the preferences pane and lock focus on one of the static text labels. The inspector will show you its parameterized attributes (it's the same set though).
It's the set of nine attributes listed in the "Text-specific parameterized attributes" of the reference documentation above.
As Bill Cheeseman mentions, his tool allows you to query for parameterized attributes, Accessibility Inspector does not have that functionality. In general, the behavior of the text area and static text in Text Edit, since it uses stock AppKit controls, is the reference for how any of those attributes should behave.
Definitely file the documentation bug though - if it is not documented, it should be. Thanks.
-James
If you return something else as the AXValue, it will confuse accessibility clients like VoiceOver.
Instead, add an NSAccessibilityDescriptionAttribute. This string can contain all of the extra information.
2. If the cell is not editable, it should already report its role as static text, and its role description should be provided automatically as well.
3. In this case, you should not provide a custom role description - the role is static text, and the element should describe its role accordingly.
4. You might want to consider getting the attributes from your superclass, and adding the additional attributes. Otherwise, if an attribute is added to text fields in the future (For instance we added AXPlaceholderValue in a recent release), then your subclass will not support it automatically.
-James
For the most part this behaves correctly except that it occasionally reads the Accessibility Content twice. While looking into this in gdb I noticed that multiple NSAccessibilityExceptions are being thrown when I turn VO on with a tweet as main focus.
2010-05-10 17:39:43.954 Syrinx[85907:a0f] NSExceptionHandler has recorded the following exception: NSAccessibilityException -- Attempt to observe "AXTextInputMarkingSessionBegan" on non-observable element: <NSTableViewCellProxy: 0x11d4ebbf0> col:0 row:33 real element:<SRXTableCell: 0x11d51e5a0> Stack trace: 0x7fff81c18a2c 0x7fff827510f3 0x7fff82ed19b9 0x7fff86485c45 0x7fff864839f5 0x7fff8618900b 0x7fff86192f6c 0x7fff8616f541 0x7fff82e16201 0x7fff82e148df 0x7fff85349ada 0x7fff853498df 0x7fff85349798 0x7fff86235a2a 0x7fff86235379 0x7fff861fb05b 0x7fff861f3d7c 0x100001365 0x100001314 0x1 (gdb) continue (gdb) continue 2010-05-10 17:39:44.641 Syrinx[85907:a0f] NSExceptionHandler has recorded the following exception: NSAccessibilityException -- Attempt to observe "AXCreated" on non-observable element: <NSTableViewCellProxy: 0x11e673ac0> col:0 row:33 real element:<SRXTableCell: 0x11d51e5a0> Stack trace: 0x7fff81c18a2c 0x7fff827510f3 0x7fff82ed19b9 0x7fff86485c45 0x7fff864839f5 0x7fff8618900b 0x7fff86192f6c 0x7fff8616f541 0x7fff82e16201 0x7fff82e148df 0x7fff85349ada 0x7fff853498df 0x7fff85349798 0x7fff86235a2a 0x7fff86235379 0x7fff861fb05b 0x7fff861f3d7c 0x100001365 0x100001314 0x1
What am I doing wrong that is causing these exceptions, and how do I fix them? _______________________ Mickey Roberson
-------------------------------------------------- James Dempsey AppKit Engineering Apple
|