Accessibility Label and The Elusive Back button

1,015 views
Skip to first unread message

mike...@aol.com

unread,
Oct 26, 2015, 10:28:33 AM10/26/15
to KIF iOS Automated Testing Framework
In general, using the free accessibility label "Back" just works in iOS apps for navigating back to the previous screen.
However, sometimes developers do "creative" things to hide or add text to the Navigation controller. It could break the usual "Back" navigation and make your app become untestable. 
You're left scratching your head and thinking, "If I could just figure out what that $$#@!! accessibilityLabel is then I could just tap it and move on to solving cold fusion!"
The accessibility inspector is not very helpful [usually] in these cases.

We recently had a KIF user banging their head against this.
My colleague (our senior developer) came up with this little nugget of help.
I thought it might help others who might have (or will) encounter this.

For this to work you have to be able to stop at a breakpoint in the app code. Does not matter if you're in the simulator or actual hardware.

1) In the visible view controller (that you want to press the back button in) set a breakpoint in viewWillAppear
2) Once stopped, go to the console pane and type:

po [[self.navigationController navigationBar] subviews]


It will return something like this:

<_UINavigationBarBackground: 0x7f6ddbb0; frame = (0 -20; 320 64); opaque = NO; autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7f682140>> - (null),

<UINavigationButton: 0x7f686c70; frame = (5 6; 33 30); opaque = NO; layer = <CALayer: 0x7f687a10>>,

<UINavigationButton: 0x81149930; frame = (269 6; 46 30); opaque = NO; layer = <CALayer: 0x8114c110>>,

<_UINavigationBarBackIndicatorView: 0x7f6dd960; frame = (8 11.5; 13 21); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f6771f0>> - Back


3) On each of those hex memory addresses, you can try this:

po [0x7f682140 accessibilityLabel]


in some cases, it might give you an EXC_BAD_ACCESS error, but at least one, maybe even two of those will expose an accessibilityLabel.

In my case, we have one that's, "Back" and another that is an empty space, " "


po [0x7f6dd960 accessibilityLabel]

Back


In addition, something I'll do, is connect to a real device, then in iTunes, select the device, and turn on the accessibility voice over by doing the following:
1) With my app launched and already navigated to my context in question..
2) ITunes > click on the device icon in the toolbar > scroll to bottom and click, "Configure accessibility..."> turn on "Voice Over".
3) In your device, tap the back button and listen for what Siri reads back audibly. 
Of course, you can't see how it's actually spelled in this case.

All accessibility labels you get for free from Apple should/will capitalize the first letter (i.e. "Back") as per Apple's accessibility spec [1]. If a developer screwed around with it, then you might try obvious things like, "back" or "BACK" or  for other general UI you might try, "thisIsCamelCase". Because they are unfamiliar with the Apple Accessibility spec [1].
In cases where the developer did do some tweaking, you may be able to find the string after you heard it read aloud by doing a case insensitive search in XCode. 

There may be other clever ways at getting to the object's accessibility label. 
Feel free to add to this post and share your experiences.

References:

Tony Mann

unread,
Nov 4, 2015, 8:56:17 AM11/4/15
to kif-fr...@googlegroups.com
This is great stuff, Mike! Thanks for sharing it.

Are there any tools we 

Tony

--
You received this message because you are subscribed to the Google Groups "KIF iOS Automated Testing Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kif-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tony Mann

unread,
Nov 4, 2015, 8:57:16 AM11/4/15
to kif-fr...@googlegroups.com
Great stuff, Mike. Thanks for sharing it.

Are there any tools we could add to KIF to facilitate this kind of sleuthing? We already have the print view hierarchy calls -- is that sufficient?

Tony

On Oct 26, 2015, at 8:28 AM, mikelupo via KIF iOS Automated Testing Framework <kif-fr...@googlegroups.com> wrote:

mike...@aol.com

unread,
Nov 4, 2015, 9:10:55 AM11/4/15
to kif-fr...@googlegroups.com
Print Hierarchy could be enough. 
I would have to investigate that to see if we expose the labels in the Navigation Menu.
I can't think of any one thing I'd like to see integrated except for maybe OHHTTPStubs.

Along the lines of object spying...It might be worthwhile to just dump the UI when a tapView... or waitForView... fails to find it's intended target. Doesn't Selenium do that?
Basically, anything that helps a user user KIF "more easily" is a good thing in my opinion.

Mike

Tony Mann

unread,
Nov 4, 2015, 9:12:27 AM11/4/15
to kif-fr...@googlegroups.com
The view dump seems like a good idea.

Tony

Adam Tews

unread,
Dec 15, 2015, 3:55:44 PM12/15/15
to KIF iOS Automated Testing Framework
+1 for debug view dump!

Eric Firestone

unread,
Dec 16, 2015, 4:09:14 AM12/16/15
to KIF iOS Automated Testing Framework
This might be helpful for view dumping:

@implementation UIView (DebugAdditions)

- (void)logRecursiveDescriptionUsingBlock:(NSString * (^)(UIView *subview))messageBlock;
{
   
NSAssert(messageBlock, @"A block returning the log message is required for subview logging.");

   
NSMutableString *logMessage = [[NSMutableString alloc] initWithString:@"\n"];
   
[self _appendDescriptionToLogMessage:logMessage depth:0 usingBlock:messageBlock];

   
NSLog(@"%@", logMessage);
}

#pragma mark - Private Methods

- (void)_appendDescriptionToLogMessage:(NSMutableString *)logMessage depth:(NSUInteger)depth usingBlock:(NSString * (^)(UIView *subview))messageBlock;
{
   
for (NSUInteger depthIndex = 0; depthIndex < depth; depthIndex++) {
       
[logMessage appendString:@"   | "];
   
}

   
NSString *description = messageBlock(self);
   
if (!description) {
        description
= @"<no description>";
   
}

   
[logMessage appendFormat:@"%@\n", description];

   
for (UIView *subview in self.subviews) {
       
[subview _appendDescriptionToLogMessage:logMessage depth:(depth + 1) usingBlock:messageBlock];
   
}
}

@end

You would then use it like so:

[view logRecursiveDescriptionUsingBlock:^(UIView *view) { return view.accessibilityIdentifier; }];

The result looks similar to what -[UIView recursiveDescription] returns, but the information on each line is customized by the return value from the block.

Tony Mann

unread,
Dec 16, 2015, 4:12:56 AM12/16/15
to kif-fr...@googlegroups.com
Note that KIF already has a UiView.printViewHierarchy method.

Tony
Reply all
Reply to author
Forward
0 new messages