SwiftUI AVPlayer - Как приостановить и возобновить воспроизведение?

Поэтому я создал представление под названием VideoElement, которое будет воспроизводить видео в фоновом режиме при загрузке родительского представления. Это сработало. Однако я не могу понять, как реализовать систему паузы / возобновления. Я хочу изменить переменную (var paused), которая приостанавливает воспроизведение видео, если true, и возобновляет воспроизведение, когда false. Это вроде работает. В частности, если для паузы установлено значение true, видео приостанавливается. Однако, когда он становится ложным, воспроизведение видео не возобновляется.

Может, может что-то делать с updateUIViewController? Кроме того, я понятия не имею, почему paused должна быть переменной привязки, а не переменной состояния (@State не работает). Любая помощь будет оценена. Спасибо!

import SwiftUI
import AVKit

struct VideoElement: View {

    var fileName: String
    @Binding var paused: Bool //this controls playback

    var body: some View {
    
        let player = AVPlayer(url: URL(fileURLWithPath: Bundle.main.path(forAuxiliaryExecutable: fileName)!))
    
        AVPlayerControllerRepresented(player: player)
            .onAppear {
                player.play()
            }
            .onChange(of: paused, perform: { paused in
                if paused {
                    player.pause()
                }
                else {
                    player.play() //should play the video, does not
                    print("resume") //this runs, so above should've run also
                }
            })
        }  
    }
}

struct AVPlayerControllerRepresented : UIViewControllerRepresentable {

    var player : AVPlayer

    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        controller.player = player
        controller.showsPlaybackControls = false
        return controller
    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
    }
}

person softandwet    schedule 17.06.2021    source источник


Ответы (1)


Я бы не рекомендовал создавать AVPlayer в body - это будет гарантировать, что каждый раз при повторном рендеринге представления игрок будет воссоздан. Вместо этого сохраните его где-нибудь, чтобы оно переживало повторные рендеры. Я выбрал для этого ObservableObject.

class PlayerManager : ObservableObject {
    let player = AVPlayer(url: URL(string: "https://media.w3.org/2010/05/sintel/trailer.mp4")!)
    @Published private var playing = false
    
    func play() {
        player.play()
        playing = true
    }
    
    func playPause() {
        if playing {
            player.pause()
        } else {
            player.play()
        }
        playing.toggle()
    }
}

struct ContentView: View {
    @StateObject var playerManager = PlayerManager()
    
    var body: some View {
        VStack {
            AVPlayerControllerRepresented(player: playerManager.player)
                .onAppear {
                    playerManager.play()
                }
            Button("Play/Pause") {
                playerManager.playPause()
            }
        }
    }
}

struct AVPlayerControllerRepresented : UIViewControllerRepresentable {
    var player : AVPlayer
    
    func makeUIViewController(context: Context) -> AVPlayerViewController {
        let controller = AVPlayerViewController()
        controller.player = player
        controller.showsPlaybackControls = false
        return controller
    }
    
    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {
        
    }
}

person jnpdx    schedule 17.06.2021