簡體   English   中英

如何在 SwiftUI 中控制 AVPlayer 播放

[英]How to control AVPlayer playback in SwiftUI

我正在嘗試在我的應用程序上播放音樂並設法從應用程序的設置中播放/停止音樂。

首先,我正在創建一個名為MusicPlayerObservableObject class :

class MusicPlayer: ObservableObject {
    
    @Published var isPlaying = AppDefaults.shared.isMusicPlaying()
    @Published var music : AVAudioPlayer? = nil
    
    func playMusic() {
        guard let strFilePath = Bundle.main.path(forResource: "music", ofType: "mp3") else { return }
        do {
            music = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: strFilePath))
        } catch {
            print(error)
        }
        
        music?.volume = 0.60
        music?.numberOfLoops = -1
        
        if isPlaying {
            music?.play()
        } else {
            music?.stop()
        }
    }
}

然后在主應用文件中播放音樂:

@main
struct AppName: App {
    
    @StateObject private var player = MusicPlayer()
    
    var body: some Scene {
        WindowGroup {
            ContentsView()
                .onAppear {
                    player.playMusic()
                }
        }
    }
}

然后嘗試使用設置中的切換來停止/播放音樂:

struct SettingsView: View {
    
    @StateObject private var player = MusicPlayer()
    
    var body: some View {
        Toggle("Music", isOn: $player.isPlaying)
            .onChange(of: player.isPlaying, perform: { _ in
                AppDefaults.shared.setMusic(player.isPlaying)
                if player.isPlaying {
                    player.music?.stop()
                } else {
                    player.music?.play()
                }
            })
    }
}

現在的問題是打開或關閉不會改變播放的 state。 我該如何解決這個問題?

這里的問題是您正在初始化您的 Viewmodel 兩次。 所以你有兩個不同的事實來源。 所以有 2 種不同的AVAudioPlayer

解決方案:在頂部視圖中創建一個實例並將其傳遞給需要它的視圖。

當您決定省略SettingsView如何與其他視圖相關時,我只能提供更通用的解決方案。

假設在AppName中使用了SettingsView

@StateObject private var player = MusicPlayer()

WindowGroup {
    ....(ContentView stuff)
    SettingsView()
        // pass the observableObject on to the SettingsView and its children
        .environmentObject(player)
}

然后在SettingsView

struct SettingsView: View {
    // get the observableObject from the environment
    @EnvironmentObject private var player: MusicPlayer
    
    var body: some View {
        Toggle("Music", isOn: $player.isPlaying)
            .onChange(of: player.isPlaying, perform: { _ in
                AppDefaults.shared.setMusic(player.isPlaying)
                if player.isPlaying {
                    player.music?.stop()
                } else {
                    player.music?.play()
                }
            })
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM