Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SwiftUI:如何正确地以模式呈现AvPlayServiceController? 适当的UIKit方法:_Swiftui_Presentmodalviewcontroller_Avplayerviewcontroller_Avkit - Fatal编程技术网

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主机控制器的用途是什么?抱歉,如果这是一个愚蠢的问题,我刚刚开始快速发展。