如何在 SwiftUI 中管理 AVPlayer 状态

2024-05-05

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

我想过创建自己的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

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一个状态对象,这样它的内存将由系统管理,并且不会重新设置它并使其保持活动状态,直到您的视图存在为止。

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") }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 SwiftUI 中管理 AVPlayer 状态 的相关文章

  • ios 在后台处理推送通知

    我想保存应用程序处于后台状态时到达的推送通知 我知道关于 void application UIApplication application didReceiveRemoteNotification NSDictionary userIn
  • 由枚举驱动的 SwiftUI 选择器:值未更新

    根据苹果公司的相关文档SwiftUI 中使用 Enum 的选取器 https developer apple com documentation swiftui picker 如果枚举符合Identifiable协议除了CaseIterab
  • 可以获取位置,但无法获取航向

    我目前只使用模拟器 但我在 iOS 模拟器上快速使用 CoreLocation 时遇到问题 我得到此代码打印的位置更新 但从未得到标题 我不想当然 我正在尝试制作一个指南针类型的应用程序 它将显示目标的方位 class CompassVie
  • AWS S3 公共对象与私有对象?

    回到 S3 我的存储桶中有图像的 URL 我将在我的应用程序中呈现这些图像 但它们被设置为私有 当我尝试单击该链接时 它显示 访问被拒绝 当我将链接的设置更改为公共时 它会通过 但是我读到公共访问并不是最安全的事情 所以这本质上是一个由两部
  • 在 iOS 上使用 Web 服务的最佳方式?

    我想构建一个 iOS 应用程序 让您登录到网络服务 之后 应用程序将 当用户选择时 通过 https 发送登录名 密码以及请求的变量 例如 在请求 新闻更新 后 它将收到 XML 格式的请求信息 类似于
  • 从命令行调试 iOS 应用程序构建

    我正在通过命令行构建 iOS 应用程序 但在调试它时遇到问题 如果我使用 XCode 进行构建 它会让我在设备上 构建和调试 而不会出现任何问题 但现在 我不知道如何使用 gdb 在设备上启动它并逐步执行它 如果我尝试 添加自定义目标 可执
  • 为什么我不能在 Realm 属性上使用 private

    我正在尝试在 RealmSwift 中存储一个枚举案例 但 Realm 不支持枚举 本文 https medium com it works locally persisting swift enumerations with realm
  • 推入 UINavigationController 时隐藏 FBFriendPickerViewController 导航栏

    介绍一个实例FBFriendPickerViewController using presentViewController animated completion 非常简单 该类似乎是针对该用例的 但是 我想推送一个实例FBFriendP
  • 以编程方式触发iOS摇动事件

    如何以编程方式触发 iOS 中的摇动事件 我尝试过以下方法 但它总是崩溃 void shake NSLog TEST UIMotionEventProxy m NSClassFromString UIMotionEvent alloc in
  • 错误:更改核心数据模型后架构armv7的重复符号

    我有一个使用核心数据框架的应用程序 我工作得很好 我刚刚更改了数据模型 向一个实体添加一个属性 当我尝试构建它时 出现错误 duplicate symbol OBJC METACLASS AccountFolder in Users XXX
  • 检测 AvPlayer 何时切换比特率

    在我的应用程序中 我使用 AVPlayer 通过 HLS 协议读取一些流 m3u8 文件 我需要知道在流会话期间 客户端切换比特率多少次 我们假设客户端的带宽正在增加 因此客户端将切换到更高比特率的段 AVPlayer能检测到这个开关吗 T
  • 我的游戏中应该有多少个视图控制器?

    我开始使用 spritekit 构建我的第一个游戏 现在我只有一个视图控制器来呈现开始屏幕场景 override func viewDidLoad super viewDidLoad let scene StartScreenScene C
  • UICollectionView 拖放文件夹创建

    我正在使用 UICollectionView 创建 iOS 画廊应用程序 我希望用户能够拖放图像来重新排序图库并创建文件夹 类似于 iPhone 上的主屏幕 我发现了以下内容tutorial http nshint io blog 2015
  • 频繁绘制 CGPath 时的性能

    我正在开发一个将数据可视化为折线图的 iOS 应用程序 该图被绘制为CGPath在全屏自定义中UIView最多包含 320 个数据点 数据经常更新 图表需要相应地重新绘制 刷新率为 10 秒就很好了 到目前为止很容易 然而 我的方法似乎需要
  • iOS 循环对象的属性并添加操作

    我有一个具有几个类似属性的类 UISliders 我想添加用户开始和结束使用每个滑块时的操作 每个滑块都将链接到同一个选择器 因此我考虑只是迭代它们 而不是编写 10 个几乎相同的代码块 问题是 最有效的方法是什么 我尝试过这样的事情 在运
  • iphone:如何停止快门动画?

    我有两个问题 1 我想知道如何在相机加载时停止快门动画 我正在使用 UIImagePickerController 我已经参考了堆栈溢出的许多答案 但没有成功 2 我在相机中有一个自定义按钮 使用cameraOverlayView并想通过单
  • 指定访问组时出现 KeychainItemWrapper 错误

    相当长一段时间以来 我一直在使用 KeychainItemWrapper 的 ARC 版本成功读取和写入私有钥匙串项目 我现在正在努力将我的 iOS 应用程序转换为使用共享访问组 以便我的 2 个共享相同应用程序前缀的应用程序可以访问钥匙串
  • 在现有 iOS 应用程序中集成 React-native(0.40.0) 后找不到 Yoga/Yoga.h 头文件

    在我的 Swift iOS 应用程序中集成 React Native 后 我无法构建 yoga Yoga h file cannot be found 我已经浏览了文档 查看了react native github页面 检查了类似问题的SO
  • WhatsApp 显示警告“此项目无法共享。请选择其他项目。”对于 iOS 应用程序。

    我正在开发一个 iOS 应用程序 在该应用程序中 我有社交共享功能 并且社交共享功能使用深度链接来共享 URL 该网址共享对于所有应用程序都运行良好 除了WhatsApp 它会显示一个警报弹出窗口 此项目无法共享 请选择其他项目 以下是我的
  • Swift 中的 UIAlert 自动消失?

    我有以下代码 Creates Alerts on screen for user func notifyUser title String message String gt Void let alert UIAlertController

随机推荐

  • Vim / vi 生存指南

    基本的 vim 命令有哪些 新用户需要了解什么才能避免陷入麻烦 请每条评论一条命令 我发现不可替代的 因为它也可以在 vi 中使用 与 vim 的视觉模式不同 是标记 您可以用以下标记标记不同的点m 小写 然后是您选择的字母 例如 x 然后
  • 如何使使用 CSS :after 元素创建的文本可选择?

    我正在使用 css 创建文本 after 但我无法选择生成的文本 例如用于复制和粘贴 是否可以使其可选择 div foo div div after content 123 sample http jsfiddle net jfbc4 2
  • 如何将点光源转换为卵形/椭圆形?

    我希望通过具有不同 x 和 y 值的 vec2 半径将当前的圆形光变成椭圆形 有没有办法根据我当前在片段着色器中的代码来做到这一点 uniform struct Light vec4 colour vec3 position vec2 ra
  • SVG/XML 中有一些innerHTML 替代品吗?

    在 HTML 中 我可以通过提供字符串形式的模板来构建一个简单的模板系统 替换其中的某些部分 然后使用innerHTML到某个容器 var templ span myText span var newContent templ replac
  • 如何动态构造方法?

    我设计了一个类 它非常标准 具有一些方法属性 class foo def f1 self print f1 def f2 self print f2 def fn self print fn 现在我想创建一个包含一组 foo 实例的类 cl
  • 是否有用于序列化和反序列化各种格式的对象层次结构的模式?

    给定一个复杂的对象层次结构 幸运的是它不包含循环引用 如何实现支持各种格式的序列化 我不是来讨论实际实施的 相反 我正在寻找可能派上用场的设计模式的提示 更准确地说 我正在使用 Ruby 我想解析 XML 和 JSON 数据以构建复杂的对象
  • Checkstyle 规则防止调用某些方法和构造函数

    是否可以使用 Checkstyle 来禁止使用某些使用系统相关默认值 区域设置 字符集等 的构造函数或方法 我更喜欢强制执行一项政策 程序员应该明确了解系统相关的值 所以我认为以下物品是危险的 all the constructors of
  • 是否需要 AudioServicesDisposeSystemSoundID?

    我最近开始使用 AudioToolbox 框架 并注意到有一个名为AudioServicesDisposeSystemSoundID 只是想知道 调用的时候不调用上面的方法是不是内存泄漏AudioServicesCreateSystemSo
  • TortoiseGit 与 TortoiseSVN 并存?

    我已经使用 TortoiseSVN 好几年了 但我正在考虑慢慢改用 git 因为我真的很喜欢它的分支和合并 我目前正在通过命令行使用 git 但正在考虑安装 TortoiseGit 有人有并排使用两只乌龟的经验吗 这有什么已知的问题吗 我真
  • TensorFlow 未编译为使用 SSE(等)指令,但这些指令是可用的

    我第一次使用一些示例代码运行 TensorFlow 运行代码时我收到以下警告 有谁知道为什么会发生这种情况以及如何解决它 2017 03 31 02 12 59 346109 W c tf jenkins home workspace re
  • 如何使用 Objective C 安全地存储数据? (Mac/可可开发)

    我正在尝试创建我的可可应用程序的试用部分 我已设置所有许可 包括密钥 等 但我想知道如何存储例如用户第一次在安全的地方运行程序的时间 用户无法轻松找到它和 或编辑它 我正在摆弄 NSUserDefaults standardUserDefa
  • CvMat 和 Imread 与 IpImage 和 CvLoadImage

    使用 OpenCv 2 4 我有两个选项来加载图像 1 CvMat and Imread 2 IpImage and CvLoadImage 使用哪一个更好 我尝试将两者混合并最终出现段错误 imread返回一个Mat not CvMat
  • tf.keras.utils.image_dataset_from_directory,但标签来自 csv?

    请告诉我哪里出错了 我正在研究 Kaggle 狗品种分类挑战 我想尝试 one hot 编码与标签编码 图像未在图像目录中拆分 因此我无法将 推断 与 tf keras utils image dataset from directory
  • Android 1.5 在设备上不再显示 Android 应用程序

    我在 Android Market 上的最新更新导致我的应用程序不再适用于 Android 1 5 设备 我更改了以下内容
  • Sequel Pro / MAMP 在哪里存储本地数据库?

    我通过 Sequel Pro 和 MAMP 在我的计算机上创建了一些数据库 并运行 localhost 来查看它们 但是 我全新安装了 Mac OS Lion 但忘记将数据库备份到 sql 文件 我会定期备份文件 并预装计算机的副本 有谁知
  • JavaFX 自定义列表单元格,updateItem 被多次调用

    我正在使用一个ListView在 JavaFX 应用程序中 列表中的项目需要的不仅仅是一个字符串来显示它们 所以我做了一个自定义实现ListCell
  • 在单个图中获取 geom_hex 中的观测值 (Shiny)

    我正在尝试创建一个十六进制的交互式图 用户可以单击给定的十六进制 并接收分组在该单击的十六进制中的原始数据帧的所有观察结果的列表 下面是一个 MWE 看起来非常接近我的目标 我正在使用 Shiny hexbin 和 ggplotly app
  • Python pandas cumsum() 在达到最大值后重置

    我有一个 pandas DataFrame 其中 timedeltas 作为这些增量的累积和 在单独的列中以毫秒表示 下面提供了一个示例 Transaction ID Time TimeDelta CumSum ms 1 00 00 04
  • 实体框架一对多关系

    我的 EF 查询大约需要 3 秒才能获取 10 个玩家 因为它获取另一个表的所有 500k 行 而不是我需要的少数行 这是玩家实体 namespace RocketLeagueStats Database Entities Table pl
  • 如何在 SwiftUI 中管理 AVPlayer 状态

    我有 SwiftUI 中的 URL 列表 当我点击某个项目时 我会呈现一个全屏视频播放器 我有一个 EnvironmentObject它处理一些查看器选项 例如 是否显示时间码 我还有一个显示和隐藏时间码的切换开关 我只在本例中包含了该切换