Home > OS >  Button Image does not refresh instantly
Button Image does not refresh instantly

Time:08-18

I want my App to play music the first time the play Button is played, after that it should swap the Button Image to pause. It doesn't refresh instantly but only after the Song is being played already and I press the play Button again 2 times.

enter image description here

enter image description here

    @State var isPlaying: Bool = false
    @StateObject var musicPlayerVM: MusicPlayerViewModel
    @StateObject var audioManager = AudioManager()

Button() {
                    if isPlaying == false {
                        audioManager.startPlayer(track: musicPlayerVM.song.track)
                        isPlaying = true
                    } else {
                        audioManager.playPause()
                    }
                } label: {
                    Image(systemName: audioManager.isPlaying ? "pause" : "play.fill")
                        .resizable()
                        .renderingMode(.template)
                        .foregroundColor(Color.white)
                        .frame(width: 19, height: 25)
                }
final class AudioManager: ObservableObject {
    var player: AVAudioPlayer?
    @Published private(set) var isPlaying: Bool = false
    
    func startPlayer(track: String) {
        guard let url = Bundle.main.url(forResource: track, withExtension: "mp3") else {return}
        
        do {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
            try AVAudioSession.sharedInstance().setActive(true)
            player = try AVAudioPlayer(contentsOf: url)
            player?.play()
        } catch {
            print("Failed to initialize player: ", error)
        }
    }
    
    func playPause() {
        guard let player = player else {
            print("Instance of audio player not found")
            return
        }
        if player.isPlaying {
            player.pause()
            isPlaying = false
        } else {
            player.play()
            isPlaying = true
        }
    }    
}
```

CodePudding user response:

You need to set isPlaying to true inside of your AudioManager class when you first start the player.

    do {
        try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
        try AVAudioSession.sharedInstance().setActive(true)
        player = try AVAudioPlayer(contentsOf: url)
        player?.play()
        isPlaying = true  // here
    } catch {
        print("Failed to initialize player: ", error)
    }

Your isPlaying in your view has a different purpose than tracking pause status, so I suggest you give it a different name such as playerStarted to avoid confusion.

A better idea is to use an enum to give your AudioManager 3 states: .stopped, .playing, and .paused and use it as the single source of truth.

  • Related