When using voice over on the springboard, when the UIPageControl at the bottom of the screen is selected, VoiceOver announces something like "Page 1 of 5. Adjustable." and the user can swipe up and down to change pages.
In my app, I do not get the "Adjustable" part, and the pages cannot be changed by swiping.
Any ideas how I fix this? It obviously kills the usability of the app.
I have subclassed UIPageControl and overrode the -accessibilityTraits getter to return UIAccessibilityTraitAdjustable getting Voice Over to read "adjustable". 
To add actions: implement the -accessibilityIncrement and -accessibilityDecrement methods specified in the UIAccessibilityAction category. 
Since my pages respond to the UIControlEventValueChanged events, I make sure to send actions for this event too.
Sample code
@interface AccessibleUIPageControl : UIPageControl
@end
@implementation AccessibleUIPageControl
- (UIAccessibilityTraits)accessibilityTraits
{
    return super.accessibilityTraits | UIAccessibilityTraitAdjustable;
}
- (void)accessibilityIncrement
{
    self.currentPage = self.currentPage + 1;
    [self sendActionsForControlEvents:UIControlEventValueChanged];
}
- (void)accessibilityDecrement
{
    self.currentPage = self.currentPage - 1;
    [self sendActionsForControlEvents:UIControlEventValueChanged];
}
@end
                        If you're supporting iOS 9 and newer, this behavior is now the standard - no special handling required.
If you're supporting iOS 8 and lower, subclass UIPageControl and override accessibilityIncrement and accessibilityDecrement. You don't need to override the accessibilityTraits property to indicate it's adjustable - UIPageControl is adjustable by default.
import UIKit
class AccessibleUIPageControl: UIPageControl {
    override func accessibilityIncrement() {
        self.currentPage += 1
        self.sendActionsForControlEvents(.ValueChanged)
    }
    override func accessibilityDecrement() {
        self.currentPage -= 1
        self.sendActionsForControlEvents(.ValueChanged)
    }
}
Then in your view controller you can listen for ValueChanged and respond appropriately to show the content for the new page:
//viewDidLoad:
self.pageControl.addTarget(self, action: "didChangePage", forControlEvents: .ValueChanged)
func didChangePage() {
    let contentOffset: CGFloat = collectionView.frame.size.width * CGFloat(pageControl.currentPage)
    collectionView.setContentOffset(CGPointMake(contentOffset, 0), animated: false)
}
Note that if you don't subclass UIPageControl this target/action will still be called but the current page dot indicator will not update.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With