SwiftUI和AVPlayer
我正在尝试在我的SwiftUI界面中使用AVPlayer层。 谷歌在这个问题上没有太多答案,事实上,有一个看起来很有希望的教程,请参见:。但是里面满是虫子。所以,我试着用我自己的方式去做 计划:创建一个UIView子类并向其中添加一个AVPlayerLayer,然后为SwiftUI包装UIView 结果是:什么都没有 以下是到目前为止我得到的信息:SwiftUI和AVPlayer,swiftui,Swiftui,我正在尝试在我的SwiftUI界面中使用AVPlayer层。 谷歌在这个问题上没有太多答案,事实上,有一个看起来很有希望的教程,请参见:。但是里面满是虫子。所以,我试着用我自己的方式去做 计划:创建一个UIView子类并向其中添加一个AVPlayerLayer,然后为SwiftUI包装UIView 结果是:什么都没有 以下是到目前为止我得到的信息: struct PlayerView : UIViewRepresentable { func makeUIView(context: Co
struct PlayerView : UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
return PlayerViewSwift()
}
func updateUIView(_ uiView: UIView, context: Context) {
}
}
然后是PlayerViewWift类:
class PlayerViewSwift : UIView {
private let playerLayer = AVPlayerLayer()
init() {
super.init(frame: .infinite)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
// This attribute hides `init(coder:)` from subclasses
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
override func layoutSubviews() {
super.layoutSubviews()
// playerLayer.player =
print("hmmm")
let player = AVPlayer(url: URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u80")!)
player.play()
playerLayer.player = player
layer.addSublayer(playerLayer)
}
}
从URL路径扩展中删除尾随的“0”,使其为“m3u8”而不是“m3u80”
另外,将playerLayer
的帧设置为playervewswift
在layoutSubviews()末尾的边界:
从URL路径扩展中删除尾随的“0”,使其为“m3u8”而不是“m3u80”
另外,将playerLayer
的帧设置为playervewswift
在layoutSubviews()末尾的边界:
Swift 5.1,iOS 13
我也阅读了Chris Mash教程(其中有4篇)并将其组合在一起。我当然不记得它们充满了bug,也许是一些拼写错误
它在SwiftUI导航控制器管理的页面中播放嵌入式视频或流媒体视频
import Foundation
import SwiftUI
import AVFoundation
import Combine
let timePublisher = PassthroughSubject<TimeInterval, Never>()
let videoFinished = PassthroughSubject<Void, Never>()
let nextFrame = PassthroughSubject<Void, Never>()
struct PlayerTimeView: View {
@State private var currentTime: TimeInterval = 0
var body: some View {
Text("\(currentTime)")
.onReceive(timePublisher) { time in
self.currentTime = time
}.statusBar(hidden: true)
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
class PlayerUIView: UIView {
private var timeObservation: Any?
private let playerLayer = AVPlayerLayer()
override init(frame: CGRect) {
super.init(frame: .zero)
let url = Bundle.main.url(forResource: "AppDemo", withExtension: "mov")
// let url = URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!
// let url = URL(string: "https://www.youtube.com/watch?v=XK8METRgK_U")!
let player = AVPlayer(url: url!)
player.play()
timeObservation = player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 0.5, preferredTimescale: 600), queue: nil) { [weak self] time in
guard let self = self else { return }
// Publish the new player time
print("time.seconds ", time.seconds)
timePublisher.send(time.seconds)
NotificationCenter.default.addObserver(self, selector: #selector(self.finishVideo), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
}
playerLayer.player = player
layer.addSublayer(playerLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = CGRect(x: 0, y: -115, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
}
@objc func finishVideo() {
print("Video Finished")
NotificationCenter.default.removeObserver(NSNotification.Name.AVPlayerItemDidPlayToEndTime)
videoFinished.send()
nextFrame.send()
}
}
struct PlayerView: UIViewRepresentable {
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerView>) {
}
func makeUIView(context: Context) -> UIView {
PlayerUIView(frame: .zero)
}
}
struct PlayerPage: View {
@EnvironmentObject var env: MyAppEnvironmentData
@Environment(\.presentationMode) var presentation
var body: some View {
VStack {
PlayerView().onReceive(videoFinished) { (_) in
self.presentation.wrappedValue.dismiss()
}
HStack {
Spacer()
PlayerTimeView()
Spacer()
}
}
}
}
<代码>导入基础
导入快捷键
进口AVF基金会
进口联合收割机
让timePublisher=PassthroughSubject()
让videoFinished=PassthroughSubject()
让nextFrame=PassthroughSubject()
结构PlayerTimeView:视图{
@状态专用变量currentTime:TimeInterval=0
var body:一些观点{
文本(“\(当前时间)”)
.onReceive(timePublisher){time in
self.currentTime=时间
}.statusBar(隐藏:真)
.navigationBarHidden(真)
.navigationBarBackButtonHidden(真)
}
}
类playerUI视图:UIView{
私人观察:有吗?
private let playerLayer=AVPlayerLayer()
重写初始化(帧:CGRect){
super.init(帧:.0)
让url=Bundle.main.url(用于资源:“AppDemo”,扩展名为“mov”)
//让url=url(字符串:https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!
//让url=url(字符串:https://www.youtube.com/watch?v=XK8METRgK_U")!
let player=AVPlayer(url:url!)
player.play()
timeObservation=player.addPeriodicTimeObserver(用于间隔:CMTime(秒:0.5,首选时间刻度:600),队列:nil){[弱自我]时间
guard let self=self-else{return}
//发布新的播放器时间
打印(“time.seconds”,time.seconds)
timePublisher.send(time.seconds)
NotificationCenter.default.addObserver(self,选择器:#选择器(self.finishVideo),名称:NSNotification.name.AVPlayerItemDidPlayToEndTime,对象:nil)
}
playerLayer.player=玩家
layer.addSublayer(playerLayer)
}
必需初始化?(编码器:NSCoder){
fatalError(“初始化(编码者:)尚未实现”)
}
覆盖func布局子视图(){
super.layoutSubviews()
playerLayer.frame=CGRect(x:0,y:-115,宽度:UIScreen.main.bounds.width,高度:UIScreen.main.bounds.height)
}
@objc func finishVideo(){
打印(“视频完成”)
NotificationCenter.default.removeObserver(NSNotification.Name.AVPlayerItemDidPlayToEndTime)
videoFinished.send()
nextFrame.send()
}
}
结构PlayerView:UIViewRepresentable{
func updateUIView(uiView:uiView,context:UIViewRepresentableContext){
}
func makeUIView(上下文:context)->UIView{
PlayerUI视图(帧:.0)
}
}
结构PlayerPage:视图{
@EnvironmentObject变量env:MyAppEnvironmentData
@环境(\.presentationMode)变量表示
var body:一些观点{
VStack{
PlayerView().onReceive(videoFinished){(u3;)in
self.presentation.wrappedValue.disclose()文件
}
HStack{
垫片()
PlayerTimeView()
垫片()
}
}
}
}
Swift 5.1,iOS 13
我也阅读了Chris Mash教程(其中有4篇)并将其组合在一起。我当然不记得它们充满了bug,也许是一些拼写错误
它在SwiftUI导航控制器管理的页面中播放嵌入式视频或流媒体视频
import Foundation
import SwiftUI
import AVFoundation
import Combine
let timePublisher = PassthroughSubject<TimeInterval, Never>()
let videoFinished = PassthroughSubject<Void, Never>()
let nextFrame = PassthroughSubject<Void, Never>()
struct PlayerTimeView: View {
@State private var currentTime: TimeInterval = 0
var body: some View {
Text("\(currentTime)")
.onReceive(timePublisher) { time in
self.currentTime = time
}.statusBar(hidden: true)
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
class PlayerUIView: UIView {
private var timeObservation: Any?
private let playerLayer = AVPlayerLayer()
override init(frame: CGRect) {
super.init(frame: .zero)
let url = Bundle.main.url(forResource: "AppDemo", withExtension: "mov")
// let url = URL(string: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!
// let url = URL(string: "https://www.youtube.com/watch?v=XK8METRgK_U")!
let player = AVPlayer(url: url!)
player.play()
timeObservation = player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 0.5, preferredTimescale: 600), queue: nil) { [weak self] time in
guard let self = self else { return }
// Publish the new player time
print("time.seconds ", time.seconds)
timePublisher.send(time.seconds)
NotificationCenter.default.addObserver(self, selector: #selector(self.finishVideo), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
}
playerLayer.player = player
layer.addSublayer(playerLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = CGRect(x: 0, y: -115, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
}
@objc func finishVideo() {
print("Video Finished")
NotificationCenter.default.removeObserver(NSNotification.Name.AVPlayerItemDidPlayToEndTime)
videoFinished.send()
nextFrame.send()
}
}
struct PlayerView: UIViewRepresentable {
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerView>) {
}
func makeUIView(context: Context) -> UIView {
PlayerUIView(frame: .zero)
}
}
struct PlayerPage: View {
@EnvironmentObject var env: MyAppEnvironmentData
@Environment(\.presentationMode) var presentation
var body: some View {
VStack {
PlayerView().onReceive(videoFinished) { (_) in
self.presentation.wrappedValue.dismiss()
}
HStack {
Spacer()
PlayerTimeView()
Spacer()
}
}
}
}
<代码>导入基础
导入快捷键
进口AVF基金会
进口联合收割机
让timePublisher=PassthroughSubject()
让videoFinished=PassthroughSubject()
让nextFrame=PassthroughSubject()
结构PlayerTimeView:视图{
@状态专用变量currentTime:TimeInterval=0
var body:一些观点{
文本(“\(当前时间)”)
.onReceive(timePublisher){time in
self.currentTime=时间
}.statusBar(隐藏:真)
.navigationBarHidden(真)
.navigationBarBackButtonHidden(真)
}
}
类playerUI视图:UIView{
私人观察:有吗?
private let playerLayer=AVPlayerLayer()
重写初始化(帧:CGRect){
super.init(帧:.0)
让url=Bundle.main.url(用于资源:“AppDemo”,扩展名为“mov”)
//让url=url(字符串:https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")!
//让url=url(字符串:https://www.youtube.com/watch?v=XK8METRgK_U")!
let player=AVPlayer(url:url!)
player.play()
timeObservation=player.addPeriodicTimeObserver(用于间隔:CMTime(秒:0.5,首选时间刻度:600),队列:nil){[弱自我]时间
guard let self=self-else{return}
//发布新的播放器时间
打印(“time.seconds”,time.seconds)
timePublisher.send(time.seconds)
NotificationCenter.default.addObserver(self,选择器:#选择器(self.finishVideo),名称:NSNotification.name.AVPlayerItemDidPlayToEndTime,对象:nil)
}
playerLayer.player=玩家
layer.addSublayer(playerLayer)
}
必需初始化?(编码器:NSCoder){
fatalError(“初始化(编码者:)尚未实现”)
}
覆盖func布局子视图(){
super.layoutSubviews()
playerLayer.frame=CGRect(x:0,y:-115,宽度:UIScreen.main.bounds.width,高度:UIScreen.main.bounds.height)
}
@objc func finishVideo(){
打印(“视频完成”)
NotificationCenter.default.removeObserver(NSNotification.Name.AVPlayerItemDidPlayToEndTime)
videoFinished.send()
nextFrame.send()
}
}
结构PlayerView:UIViewRepresentable{
func updateUIView(uiView:uiView,上下文: