swiftuiavaudioplayerplaysound

How to play/pause sound when button is pressed


I need to play sound (it's in Assets) when I press the button. I got error: "Audio file could not be found" I got this class:

import SwiftUI
import AVFoundation

class AudioPlayerViewModel: ObservableObject {
  var audioPlayer: AVAudioPlayer?

  @Published var isPlaying = false

  init() {
      if let sound = Bundle.main.path(forResource: "thesound", ofType: "mp3") {
      do {
        self.audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: sound))
      } catch {
        print("AVAudioPlayer could not be instantiated.")
      }
    } else {
      print("Audio file could not be found.")
    }
  }

  func playOrPause() {
    guard let player = audioPlayer else { return }

    if player.isPlaying {
      player.pause()
      isPlaying = false
    } else {
      player.play()
      isPlaying = true
    }
  }
    
    
}

The I got this Button in ContentView:

Button(action: {
            audioPlayerViewModel.playOrPause()
          }) {
            Image(audioPlayerViewModel.isPlaying ? "pause" : "play")
              .resizable()
              .scaledToFit()
              .frame(width: 80, height: 80)
              .foregroundColor(.white)

Thank you!

I tried adding inDirectory: "Assets" into if let sound = Bundle.main.path(forResource: "thesound", ofType: "mp3", inDirectory: "Assets") but it didn't helped


Solution

  • If the file is in the asset catalog it's invisible in the application bundle.
    Audio files are data assets, you have to access it with NSDataAsset

    Replace

    if let sound = Bundle.main.path(forResource: "thesound", ofType: "mp3") {
        do {
          self.audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: sound))
        } catch {
          print("AVAudioPlayer could not be instantiated.")
        }
    } else {
        print("Audio file could not be found.")
    }
    

    with

    if let asset = NSDataAsset(name: "thesound") {
        do {
           self.audioPlayer = try AVAudioPlayer(data: asset.data, fileTypeHint: "mp3")
        } catch {
           print("AVAudioPlayer could not be instantiated.", error)
        }
    } else {
        print("Audio file could not be found.")
    }
    

    Note: The argument of NSDataAsset(name must be the name of the asset, not the name of the audio file.