How to tie Voiceover into an MPVolumeView Slider?

App Development

I created an MPVolumeView slider in Interface Builder to adjust the audio volume (code below):

import UIKit

import MediaPlayer

class StreamVolumeTableViewCell: AudioStreamTableViewCell

static let identifier = "StreamVolumeTableViewCell"

override func awakeFromNib() {


self.volumeSlider.setRouteButtonImage(UIImage(named: "black_route_button"), for: .normal)

self.volumeSlider.showsRouteButton = false


@IBOutlet var volumeSlider: MPVolumeView!

Now I want to make it accessible and tie in Voiceover.

I enabled accessibility on the slider, set its label ("Sound volume."), and set the 'User Interaction Enabled', 'Adjustable', and 'Allows Direct Interaction' traits. When I turn Voiceover on, it speaks the label and default hint, BUT --- when I swipe up and down, the volume slider's value does not change.

It does not appear that my finger flicks are getting through to the slider.

Also, when I adjust the volume with the hardware buttons on an actual device, the volume changes, but no updates are spoken when VO is turned on.

How do I accomplish what I'm after?




Submitted by techluver on Tuesday, February 27, 2018

I'm not amazing at swift, so forgive me if this seems weird.
VO requires standard controls to work properly. Did you actually drag a slider control into your storyboard and link it that way? Or did you design something custom?

Submitted by Mane on Tuesday, February 27, 2018

In reply to by techluver

I inserted a UIView into a TableViewCell in IB, and changed its class to MPVolumeView. Then I control-dragged a line from my nib into my Swift code to create an outlet variable.

Submitted by splyt on Tuesday, February 27, 2018

Standard components are accessible with VoiceOver because their implementation take care of setting and dealing with accessibility properties correctly, something that does not seem to happen with your component.
You created a custom component by changing a UIView into something not related. When the screen reader finds your MPView component, it treats that as a generic UIView, because that is precisely what it is.
I have not the details about how you managed to compose components on MPView visually. But as far as VoiceOver is concerned it can not deduce that whatever you set to happen visually on that view corresponds to a slider change.
You need to inherite your new class from UIView and research how to feed the several properties that VoiceOver uses to report information back adequately. At the end this is what the standard Apple components do anyways.

Submitted by Mane on Tuesday, February 27, 2018

As you saw, I initially created my volume slider by inserting a UIView into my interface using IB, and renaming the class to 'MPVolumeView'. After more reading, I suspected this is why Voiceover was not getting any of my flicks on the slider it created within the UIView.

I deleted the UIView and replaced it with a UISlider in IB, and renamed THAT class to 'MPVolumeView'. Now Voiceover responds as expected, getting all my finger flicks to change the slider value, and the volume changes on my device. I had to make sure the new slider-based control exposed the same outlet variable, but beyond that, I didn't have to change any of my code.