如何在SwiftUI中控制AVPlayer播放



我正在尝试在我的应用程序上播放音乐,并设法从应用程序的设置中播放/停止音乐。

首先,我正在创建一个名为MusicPlayer:的ObservableObject

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()
}
})
}
}

现在的问题是,打开或关闭并不能改变比赛的状态。如何解决此问题?

这里的问题是您要初始化Viewmodel两次。所以你有两个不同的真相来源。因此存在两种不同的CCD_ 3。

解决方案:在顶部视图中创建一个实例,并将其传递给需要此实例的视图。

由于您决定省略SettingsView如何与其他视图关联,我只能给出一个更通用的解决方案。

假设SettingsView用于AppName:

@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()
}
})
}
}

最新更新