How to play/pause sound when button is pressed

62 views Asked by At

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

2

There are 2 answers

1
vadian On BEST ANSWER

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.

1
sotikouk On

Try this:

if let sound = Bundle.main.url(forResource: "thesound", withExtension: "mp3")