AVAudioPlayer setVolume with fading – properly


It’s been a while since Apple added Swift fading support to AVAudioPlayer. I can’t remember when exactly, but I think it might have been since iOS 10.0. I have not used it in quite some time and recently had the need. The API is pretty straight forward, but I wasn’t actually getting the fading to happen without the volume jumping straight to the destination volume. I thought it might be a bug.

musicPlayer.setVolume(to, fadeDuration: fadeTime)

After wondering what the hell was going on, I thought maybe it’s not rendering correctly because it’s blocked or something. This fixes it right up…

DispatchQueue.main.asyncAfter(deadline: .now() + 0.0) {
    self.musicPlayer.setVolume(to, fadeDuration: fadeTime)

I can now get the various players I’m using to perform their fading perfectly – with a very tiny delay – because the fading is happening on the main thread (async).

It’s a small thing, but it’s not mentioned in the documentation that I could quickly see.

Below does essentially the same thing as the code above (no delay). This is because the call on the main thread is called asynchronously. Due to the async dispatch, the code in the closure will not be executed immediately, only on the next runloop of main, which could result in a measurable delay .

DispatchQueue.main.async {
    self.musicPlayer.setVolume(to, fadeDuration: fadeTime)

2 thoughts on “AVAudioPlayer setVolume with fading – properly

  1. Thanks, this does work. Any idea why setVolume(_:fadeDuration:) won’t work normally here? If you start the volume at 1.0 and fade to 0.0 it works normally without needing the DispatchQueue call. Very strange that you need the DispatchQueue call just because you’re fading in the other direction.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.