AVPlayer 在 macOS SwiftUI 应用程序中加载新剧集后意外自动暂停

问题描述 投票:0回答:1

我正在使用 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
    }
}

观察到的行为:

  • 在播放过程中,当选择新剧集时,当前播放的剧集会立即自动暂停,这是无意的。应用程序的预期行为是等待明确的用户操作来暂停或播放所选剧集。

采取的步骤:

  • 确保播放和暂停操作仅由用户交互触发。
  • 实现了一个标志来区分用户启动的播放和系统启动的操作。
  • 在播放剧集之前添加了延迟,以避免潜在的竞争状况。
  • 以最小的设置隔离 AVPlayer 来复制问题,确认它在简化的环境中仍然存在。

问题:

有人在使用 SwiftUI 开发的 macOS 应用程序上遇到过类似的 AVPlayer 问题吗?播放过程中选择新剧集后,什么可能会导致立即自动暂停?如何防止这种情况发生?

任何见解或建议将不胜感激。

macos swiftui audio avfoundation avplayer
1个回答
0
投票

我通过修改代码以在选择时存储所选剧集的索引,而不是立即加载和播放剧集来解决自动暂停/播放问题。

以下是一些代码调整的示例:

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.
}
© www.soinside.com 2019 - 2024. All rights reserved.