我正在使用 SwiftUI 开发一个简化的 macOS 应用程序,该应用程序使用 AVPlayer 播放播客剧集。尽管确保应用程序不会自动播放或自动暂停剧集,但我遇到了 AVPlayer 在加载新剧集后自动暂停的问题。
这是我播放剧集的逻辑的简化版本:
import SwiftUI
import AVFoundation
struct ContentView: View {
@StateObject private var playerViewModel = PlayerViewModel()
var body: some View {
VStack {
// UI for listing episodes
List(playerViewModel.episodeURLs.indices, id: \.self) { index in
Button(action: {
playerViewModel.loadEpisode(at: index)
}) {
Text("Episode \(index + 1)")
}
}
// Play/Pause button
Button(action: playerViewModel.togglePlayPause) {
Image(systemName: playerViewModel.isPlaying ? "pause.fill" : "play.fill")
}
}
}
}
class PlayerViewModel: ObservableObject {
@Published var player = AVPlayer()
@Published var isPlaying = false
@Published var selectedEpisodeIndex: Int?
private var playRequestedByUser = false
let episodeURLs = [
URL(string: ""https://traffic.libsyn.com/secure/skepticsguide/skepticast2024-04-06.mp3")!,
URL(string: "https://traffic.libsyn.com/secure/skepticsguide/skepticast2024-03-30.mp3")!
]
func loadEpisode(at index: Int) {
// Logic to load and prepare an episode
let item = AVPlayerItem(url: episodeURLs[index])
player.replaceCurrentItem(with: item)
player.pause()
isPlaying = false
playRequestedByUser = false
}
func togglePlayPause() {
if isPlaying {
pauseEpisode()
} else {
playRequestedByUser = true
playEpisode()
}
}
private func playEpisode() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
if self.playRequestedByUser {
self.player.play()
self.isPlaying = true
}
}
}
private func pauseEpisode() {
player.pause()
isPlaying = false
playRequestedByUser = false
}
}
观察到的行为:
采取的步骤:
问题:
有人在使用 SwiftUI 开发的 macOS 应用程序上遇到过类似的 AVPlayer 问题吗?播放过程中选择新剧集后,什么可能会导致立即自动暂停?如何防止这种情况发生?
任何见解或建议将不胜感激。
我通过修改代码以在选择时存储所选剧集的索引,而不是立即加载和播放剧集来解决自动暂停/播放问题。
以下是一些代码调整的示例:
class PlayerViewModel: ObservableObject {
func loadEpisodeWithoutPlaying(at index: Int) {
guard episodes.indices.contains(index) else { return }
let episode = episodes[index]
let item = AVPlayerItem(url: episode.url)
player.replaceCurrentItem(with: item)
selectedEpisodeIndex = index
isPlaying = false
}
func togglePlayPause() {
guard let index = selectedEpisodeIndex, episodes.indices.contains(index) else { return }
let selectedEpisodeURL = episodes[index].url
if let currentAsset = player.currentItem?.asset as? AVURLAsset, currentAsset.url == selectedEpisodeURL {
isPlaying ? player.pause() : player.play()
isPlaying.toggle()
} else {
loadAndPlayEpisode(at: index)
}
}
// The loadAndPlayEpisode and playEpisode methods ensure that
// episodes are played only when explicitly requested by the user.
}