skip to Main Content

I have a stupid issue but for some reason I can’t resolve it. I try to play sound with AVAudioPlayer but can’t hear anything. There are no errors, but still my app is silent. Its built with SwiftUI. This is a piece of code:

struct SoundsListView: View {
    
   var body: some View {
        List(Helpers.shared.sounds, id:.self) { item in
            Text(item)
            Spacer()
            Button(action: {
                var soundPlayer: AVAudioPlayer?
                guard let audioFile: URL = Bundle.main.url(forResource: "Analog watch", withExtension: "mp3") else { return }
                do {
                    soundPlayer = try AVAudioPlayer(contentsOf: audioFile)
                    print(soundPlayer)
                    guard let player = soundPlayer else { return }
                   player.play()
                } catch let error {
                    print("Cannot play sound")
                }
            }) {
                Image(systemName: "play")
            } //: BUTTON
        }
    }
} 

There are no errors, also sound files have target membership set.
(What is strange it’s that the same piece of code works with my older project, but written in Swift + Storyboards)

There is no sound generated neither in simulator nor hardware device. Silent mode is off, volume set to max.
I have no idea what’s wrong here.

BTW: This app sends notifications to user and sound is OK. But not in this piece of code

2

Answers


  1. Your AVAudioPlayer only exists in the scope of your button action, so it’s deallocated before the sound can play. You need to save it somewhere… I think you could declare it in SoundsListView as a @State var, but it may be better to refactor it out of the SwiftUI view entirely.

    EDIT: You probably also need to set your AVAudioSession, which lets you change playback category and control how your audio interacts with other audio e.g. music playback.

    Example:

    do {
        try AVAudioSession.sharedInstance().setCategory(.playback)
        try AVAudioSession.sharedInstance().setCategory(.playback, options: [.mixWithOthers])
        try AVAudioSession.sharedInstance().setActive(true)
    } catch {
        print(error)
    }
    
    Login or Signup to reply.
  2. For me the audio would only work sometimes. I had to ensure that when I declared my audio player in the SwiftUI View, it was an @State object. After I added @State before my property it played every time! I am importing AVKit on a separate file where I have my audio play functions… something like I have pasted below. Lmk if you need more clarification.

    //In my View I have something like this at the top 
    
    struct ContentView: View {
        
        @State var vm = PlayViewModel()   
    
    //When I want some audio to play I call it like this...                      vm.play(fileNamed: "blip")
    //And the rest of my SwiftUI code below
    
    }
    

    //And then this is what I have setup in a separate Swift file.

    import AVKit

    class PlayViewModel {
        
        private var audioPlayer: AVAudioPlayer!
        
        
        func play(fileNamed:String) {
            let sound = Bundle.main.path(forResource: fileNamed, ofType: "wav")
            
            audioPlayer?.prepareToPlay() //maybe not needed?  idk
    
            do {
                audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: sound!))
                audioPlayer?.play()
            } catch {
                print(error)
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search