inkling/Subliminal

UICollectionViewCell filtered out of Accessibility Element Path

b-levinger opened this issue · 5 comments

I ran into an issue with trying to click a button that is a child of a UICollectionViewCell, when the SLAccessibilityPath builds up it's path filterRawAccessibilityElementPath skips over the cell in the hierarchy which causes the button to never become tappable.

I fixed it with a quick hack by adding:

if ([self isKindOfClass:[UICollectionViewCell class]]) {
return YES;
}

in NSObject+SLAccessibilityHierarchy - (BOOL)classForcesPresenceInAccessibilityHierarchy

Actually, there's more involved than you think. UIAutomation creates mock accessibility containers for table view cells and collection view cells. You CANNOT tap a table view cell, even when you think you are, you are actually tapping a UITableViewCellAccessibilityElement. I have a pull request that addresses this:
#171

I'm not trying to tap the cell, there's a UIButton inside the cell that I'm trying to tap. When the cell is filtered out of the hierarchy the UIButton never becomes tappable, with the hack above it works.

Yes, but along the lines of what I was explaining, you never tap a UIButton, you're actually tapping a UIAccessibilityMockView with the same traits as your button. But -- awesome that hack works, nice catch.

You're actually both right. :) As @jzucker2 suggests, what we ultimately need to do is get UIAutomation to manipulate the mock views corresponding to the cell and its contents. We can't reference such mock views directly, though, because their classes are private--so we collect the real views instead. I think it would be more appropriate to amend -classForcesPresenceOfMockingViewsInAccessibilityHierarchy than -classForcesPresenceInAccessibilityHierarchy:

@implementation UICollectionViewCell (SLAccessibilityHierarchy)
- (BOOL)classForcesPresenceOfMockingViewsInAccessibilityHierarchy {
    return YES;
}
@end

but @brandonlevinger had the gist of the fix. (Nice debugging!)

It doesn't matter that we put real vs. mocked views in the path since they share the same accessibility information--serialized (as elements()["theirSharedAccessibilityIdentifier"]), they're indistinguishable.

@jzucker2 you may be amused to know that the mock views only appear in iOS 7--in 6, the cells themselves are accessible; and even in 7, there's only a mock view for the cell itself, not its contents--the mock cell vends the actual subviews of the cell as its accessibility children. 😝