batsansierra
batsansierra

Reputation: 334

showsRouteButton from MPVolumeView is deprecated

Since iOS 13, showsRouteButton from MPVolumeView has been deprecated

let vv = MPVolumeView()
vv.showsRouteButton = false

Warning is :

'showsRouteButton' was deprecated in iOS 13.0: Use AVRoutePickerView instead.

Apple is telling me to use AVRoutePickerView for routing, which makes no sense as in my case I do not want to use any routing stuff, I only want to hide it. It seems there's no more not deprecated way to do this.

If it's deprecated it should be hidden by default else apple should allow us to hide it...

Am I right to say it's an apple API error ?

Upvotes: 10

Views: 2122

Answers (3)

snakehnb
snakehnb

Reputation: 63

This works for me, not sure if it robust:

import MediaPlayer

extension MPVolumeView {
    
    /// Compiler warning 'showsRouteButton' was deprecated in iOS 13.0: Use AVRoutePickerView instead.
    /// But the route button will show by default if we don't set it false.
    /// We can set by key value to silent the warning. But also need prevent Apple remove the key in the future.
    func hideRouterButtonIfNecessary() {
        let bugKey = "showsRouteButton"
        var count: UInt32 = 0
        guard let properties = class_copyPropertyList(MPVolumeView.self, &count) else { return }
        for i in 0..<Int(count) {
            let property = properties[i]
            let name = property_getName(property)
            let str = String(cString: name)
            if str == bugKey {
                self.setValue(false, forKey: bugKey)
                break
            }
        }
        free(properties)
    }
}

Upvotes: 0

pommy
pommy

Reputation: 4659

Safe and forward compatible

In iOS 15.0 the route button of MPVolumeView shows the route button as a subview. The safest way to get rid of it without a deprecation warning is to look for the button and hide it:

volume.subviews.first(where: { $0 is UIButton })?.isHidden = true

Unlike just ignoring the warning or setting the value with key-value coding (as suggested by @spasbil), this will not crash the app in a future iOS release where Apple may have removed the deprecated showsRouteButton. However, it has the disadvantage of leaving an empty space right of the slider.


Setting the value through key-value coding does lead to a visually more satisfying solution, where the slider extends over the full width of the MPVolumeView. Using a #keypath expression as suggested by @spasbil shows the same warning in Xcode 13.0. Using a String literal rather than a #keypath expression, as suggested in a comment, avoids this warning. It does not resolve the danger of crashing on future iOS releases where showsRouteButton will have disappeared.

Apple never tells us when they will remove a deprecated property, but they rarely do it in a minor release. So we can hope that showsRouteButton will stay around at least for iOS 15.* releases. A forward compatible way to get rid of the route button is therefore:

if #available(iOS 16, *) {
    volumeView.subviews.first(where: { $0 is UIButton })?.isHidden = true
} else {
    volumeView.setValue(false, forKey: "showsRouteButton")
}

We might need to get back to this during the next major release beta season, presumably next summer. In the meantime, use this at your own risk. In the unlikely case that Apple removes the property in a later release of iOS 15.*, your app will crash. In the more likely case that showsRouteButton stays available but deprecated in iOS 16, your MPVolumeView will leave some unwanted space until you bump up the availability check.

Upvotes: 1

spasbil
spasbil

Reputation: 279

For now just to remove the warning and the default route button I used this immediately after initializing the MPVolumeView.

    if volumeView.value(forKey: #keyPath(MPVolumeView.showsRouteButton)) as? Bool == true {
        volumeView.setValue(false, forKey: #keyPath(MPVolumeView.showsRouteButton))
    }

I check via key value paths if the value of showsRouteButton is true and sets it to false if it is.

Upvotes: 2

Related Questions