gpt4 book ai didi

ios - 如何在 SwiftUI 中管理 AVPlayer 状态

转载 作者:行者123 更新时间:2023-12-05 02:03:31 24 4
gpt4 key购买 nike

我在 SwiftUI 中有一个 URL 列表。当我点击一个项目时,我会呈现一个全屏视频播放器。我有一个 @EnvironmentObject 来处理一些查看器选项(例如,是否显示时间码)。我还有一个显示和隐藏时间码的开关(我只在这个例子中包含了开关,因为时间码 View 无关紧要)但是每次我更改开关时都会再次创建 View ,这会重新设置 AVPlayer。这是有道理的,因为我在 View 的初始化程序中创建播放器。

我考虑过创建自己的 ObserveredObject 类来包含一个 AVPlayer 但我不确定如何或在哪里初始化它,因为我需要给它一个URL,我只从 CustomPlayerView 的初始化程序中知道。我还考虑过将播放器设置为 @EnvironmentObject 但是初始化我可能不需要的东西似乎很奇怪(如果用户没有点击 URL 来启动播放器)。

请问创建一个 AVPlayer 并交给 AVKit 的 VideoPlayer 的正确方法是什么?这是我的示例代码:

class ViewerOptions: ObservableObject {
@Published var showTimecode = false
}

struct CustomPlayerView: View {

@EnvironmentObject var viewerOptions: ViewerOptions

private let avPlayer: AVPlayer

init(url: URL) {
avPlayer = AVPlayer(url: url)
}

var body: some View {
HStack {
VideoPlayer(player: avPlayer)
Toggle(isOn: $viewerOptions.showTimecode) { Text("Show Timecode") }
}
}
}

最佳答案

您可以在此处采用多种方法。您可以尝试一下,看看哪一个最适合您。

选项 1:正如您所说,您可以将 avPlayer 包装在一个新的 ObserveredObject 类中

class PlayerViewModel: ObservableObject {
@Published var avPlayer: AVPlayer? = nil
}

class ViewerOptions: ObservableObject {
@Published var showTimecode = false
}


@main
struct DemoApp: App {
var playerViewModel = PlayerViewModel()
var viewerOptions = ViewerOptions()

var body: some Scene {
WindowGroup {
CustomPlayerView(url: URL(string: "Your URL here")!)
.environmentObject(playerViewModel)
.environmentObject(viewerOptions)
}
}
}

struct CustomPlayerView: View {
@EnvironmentObject var viewerOptions: ViewerOptions
@EnvironmentObject var playerViewModel: PlayerViewModel

init(url: URL) {
if playerViewModel.avPlayer == nil {
playerViewModel.avPlayer = AVPlayer(url: url)
} else {
playerViewModel.avPlayer?.pause()
playerViewModel.avPlayer?.replaceCurrentItem(with: AVPlayerItem(url: url))
}
}

var body: some View {
HStack {
VideoPlayer(player: playerViewModel.avPlayer)
Toggle(isOn: $viewerOptions.showTimecode) { Text("Show Timecode") }
}
}
}

选项 2:您可以将 avPlayer 作为可选属性添加到您已经存在的类 ViewerOptions 中,然后在需要时对其进行初始化

class ViewerOptions: ObservableObject {
@Published var showTimecode = false
@Published var avPlayer: AVPlayer? = nil
}

struct CustomPlayerView: View {

@EnvironmentObject var viewerOptions: ViewerOptions

init(url: URL) {
if viewerOptions.avPlayer == nil {
viewerOptions.avPlayer = AVPlayer(url: url)
} else {
viewerOptions.avPlayer?.pause()
viewerOptions.avPlayer?.replaceCurrentItem(with: AVPlayerItem(url: url))
}
}

var body: some View {
HStack {
VideoPlayer(player: viewerOptions.avPlayer)
Toggle(isOn: $viewerOptions.showTimecode) { Text("Show Timecode") }
}
}
}

选项 3:让您的 avPlayer 成为一个状态对象,这样它的内存将由系统管理,它不会重新设置它并为您保持事件状态,直到您的 View 存在。

class ViewerOptions: ObservableObject {
@Published var showTimecode = false
}

struct CustomPlayerView: View {

@EnvironmentObject var viewerOptions: ViewerOptions
@State private var avPlayer: AVPlayer

init(url: URL) {
_avPlayer = .init(wrappedValue: AVPlayer(url: url))
}

var body: some View {
HStack {
VideoPlayer(player: avPlayer)
Toggle(isOn: $viewerOptions.showTimecode) { Text("Show Timecode") }
}
}
}

选项 4:在需要时创建您的 avPlayer 对象并忘记它(不确定这是否是您的最佳方法,但如果您不需要播放器对象来执行自定义操作,那么您可以使用此选项)

class ViewerOptions: ObservableObject {
@Published var showTimecode = false
}

struct CustomPlayerView: View {

@EnvironmentObject var viewerOptions: ViewerOptions
private let url: URL

init(url: URL) {
self.url = url
}

var body: some View {
HStack {
VideoPlayer(player: AVPlayer(url: url))
Toggle(isOn: $viewerOptions.showTimecode) { Text("Show Timecode") }
}
}
}

关于ios - 如何在 SwiftUI 中管理 AVPlayer 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65132038/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com