SwiftUI:如何正确地以模式呈现AvPlayServiceController? 适当的UIKit方法:
根据苹果公司的说法,SwiftUI:如何正确地以模式呈现AvPlayServiceController? 适当的UIKit方法:,swiftui,presentmodalviewcontroller,avplayerviewcontroller,avkit,Swiftui,Presentmodalviewcontroller,Avplayerviewcontroller,Avkit,根据苹果公司的说法,avplayervewcontroller应该以模式呈现,以利用API的所有最新全屏功能。这是建议从您的UIKit视图控制器调用的示例代码: // Create the player let player = AVPlayer(url: videoURL) // Create the player view controller and associate the player let playerViewController = AVPlayerViewControlle
avplayervewcontroller
应该以模式呈现,以利用API的所有最新全屏功能。这是建议从您的UIKit视图控制器调用的示例代码:
// Create the player
let player = AVPlayer(url: videoURL)
// Create the player view controller and associate the player
let playerViewController = AVPlayerViewController()
playerViewController.player = player
// Present the player view controller modally
present(playerViewController, animated: true)
这是预期的工作,并启动了美丽的全屏视频
与SwiftUI?实现相同的效果:
为了使用SwiftUI中的avplayervewcontroller
,我创建了UIViewControllerRepresentable
实现:
struct AVPlayerView: UIViewControllerRepresentable {
@Binding var videoURL: URL
private var player: AVPlayer {
return AVPlayer(url: videoURL)
}
func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
playerController.player = player
playerController.player?.play()
}
func makeUIViewController(context: Context) -> AVPlayerViewController {
return AVPlayerViewController()
}
}
我似乎不知道如何从SwiftUI直接展示这个
与直接显示avplayervewcontroller
的方式相同
来自UIKit。我的目标只是获得所有默认的全屏好处
到目前为止,以下措施尚未奏效:
- 如果我使用
修改器并从工作表中显示它,那么播放器将嵌入工作表中,而不是全屏显示李>.sheet
- 我还尝试在UIKit中创建一个自定义的空视图控制器,该控制器通过
方法简单地显示我的viewdidappease
。这可以让播放器全屏显示,但在显示视频之前,它也会显示一个空的视图控制器,我不希望用户看到李>avplayerwcontroller
任何想法都将不胜感激 如果您喜欢像UIKit一样全屏显示,您是否尝试了ContentView中的以下代码
import SwiftUI
import UIKit
import AVKit
struct ContentView: View {
let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
@State private var vURL = URL(string: "https://www.radiantmediaplayer.com/media/bbb-360p.mp4")
var body: some View {
AVPlayerView(videoURL: self.$vURL).transition(.move(edge: .bottom)).edgesIgnoringSafeArea(.all)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct AVPlayerView: UIViewControllerRepresentable {
@Binding var videoURL: URL?
private var player: AVPlayer {
return AVPlayer(url: videoURL!)
}
func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
playerController.modalPresentationStyle = .fullScreen
playerController.player = player
playerController.player?.play()
}
func makeUIViewController(context: Context) -> AVPlayerViewController {
return AVPlayerViewController()
}
}
Razib Mollick解释的解决方案对我来说是一个很好的开始,但它缺少了SwiftUI
.sheet()
方法的使用。我在ContentView
中添加了以下内容:
@State private var showVideoPlayer=false
var body:一些观点{
按钮(操作:{self.showVideoPlayer=true}){
文本(“开始视频”)
}
.sheet(显示:$showVideoPlayer){
AVPlayerView(视频URL:self.$vURL)
.edgesIgnoringSafeArea(.all)
}
}
但问题是,当SwiftUI重新呈现UI时,AVPlayer会一次又一次地被实例化。
因此,AVPlayer的状态必须移动到存储在环境中的类
对象,以便我们可以从视图结构
获取它。因此,我的最新解决方案如下所示。我希望它能帮助别人
class PlayerState:observeObject{
公共播放器:AVPlayer?
私有视频URL:URL?
公共func播放器(用于url:url)->AVPlayer{
如果let player=currentPlayer,url==videoUrl{
还击球员
}
currentPlayer=AVPlayer(url:url)
视频url=url
返回当前玩家!
}
}
结构ContentView:View{
@环境对象变量playerState:playerState
@状态私有变量vURL=URL(字符串:https://www.radiantmediaplayer.com/media/bbb-360p.mp4")
@国家私有var showVideoPlayer=false
var body:一些观点{
按钮(操作:{self.showVideoPlayer=true}){
文本(“开始视频”)
}
.sheet(显示:$showVideoPlayer,onDismiss:{self.playerState.currentPlayer?.pause()}){
AVPlayerView(视频URL:self.$vURL)
.edgesIgnoringSafeArea(.all)
.environmentObject(self.playerState)
}
}
}
结构内容视图\u预览:PreviewProvider{
静态var预览:一些视图{
ContentView()
.environmentObject(PlayerState())
}
}
结构AVPlayerView:UIViewControllerRepresentable{
@环境对象变量playerState:playerState
@绑定var-videoURL:URL?
func updateUIViewController(\uPlayerController:AVPlayerServiceWCONTROLLER,上下文:上下文){
}
func makeUIViewController(上下文:context)->avplayervewcontroller{
让playerController=AVPlayerViewController()
playerController.modalPresentationStyle=.fullScreen
playerController.player=playerState.player(用于:videoURL!)
playerController.player?.play()
返回播放控制器
}
}
需要注意的事项(bug?):每当使用.sheet()
显示模式工作表时,环境对象不会自动传递到子视图。必须使用environmentObject()
添加它们。
这里有一个链接,可以阅读有关此问题的更多信息:Xcode 12·iOS 14 → 使用
.fullScreenCover
而不是.sheet
就可以了
另请参见:您可以在当前视图上覆盖AVPlayerView()。您希望真正的全屏覆盖所有内容还是仅覆盖某个视图,因此不包括选项卡栏?当以
工作表显示时,这对我很有效。工作表将显示为快捷方式,顶部有一个小间隙。如果旋转设备或点击左上角的“扩展到全屏”按钮,播放机将进入全屏模式。toPresent=ui主机控制器的用途是什么?抱歉,如果这是一个愚蠢的问题,我刚刚开始快速发展。