Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to set accessibilityIdentifier of UISegmentedControl's segments

I found out, that even though I could set accessibilityLabel of UISegmentedControl's segment (see: How do I set the accesibility label for a particular segment of a UISegmentedControl?), I couldn't set accessibilityIdentifier, which was equally important for my project. I need to target a segment irrespective of its text and accessibilityLabel for automation purposes.

For example, the code:

NSString *name = [NSString stringWithFormat:@"Item %li", (long)idx];
segment.accessibilityIdentifier = name;
NSLog(@"ID: %@", segment.accessibilityIdentifier);

results in:

ID: (null)

No exceptions are thrown.

Does anybody have insight into why accessibilityLabel is implemented, but not accessibilityIdentifier?

like image 436
Matt Pennig Avatar asked Apr 04 '14 21:04

Matt Pennig


2 Answers

Here is an example of looping through the views to set the accessibilityIdentifier by referencing the segment title. Unfortunately when you set the identifier it doesn't persist. UISegments must be doing some tricky overriding. Still at a loss for how to get this to work.

extension UISegmentedControl {

    /// Sets accessibility for segment buttons
    func setAccessibilityIdentifier(_ accessibilityIdentifier: String, for segmentTitle: String) {

        guard let segment = subviews.first(where: {
            $0.subviews.contains(where: { ($0 as? UILabel)?.text == Optional(segmentTitle) })
        }) else { return }

        segment.accessibilityIdentifier = accessibilityIdentifier
    }

}
like image 54
Patrick Avatar answered Nov 08 '22 20:11

Patrick


I got around this issue by writing a Swift extension for XCUIElement that added a new method tap(at: UInt). This method gets the buttons query of the element and sort the results based on their x position. This allows us to specify which segment of the UISegmentedControl we want to tap rather than relying on the button text.

extension XCUIElement {
    func tap(at index: UInt) {
        guard buttons.count > 0 else { return }
        var segments = (0..<buttons.count).map { buttons.element(boundBy: $0) }
        segments.sort { $0.0.frame.origin.x < $0.1.frame.origin.x }
        segments[Int(index)].tap()
    }
}
like image 45
Daniel Wood Avatar answered Nov 08 '22 20:11

Daniel Wood