我试图在macOS 10.15.4上使用XCode 11.5创建一个简单的SwiftUI应用程序,使用AVKitAVFoundation来播放存储在本地文件系统上的视频。我希望能够根据用户的操作(例如从一系列的菜单选项中选择)确定的文件路径来选择电影。
我从这里找到了一个代码片段。https:/qiita.comcroquette0212itemseb97e970d1dcfa2932fd。
import SwiftUI
import AVKit
import AVFoundation
class VideoItem: ObservableObject {
@Published var player: AVPlayer = AVPlayer()
@Published var playerItem: AVPlayerItem?
func open(_ url: URL) {
let asset = AVAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)
self.playerItem = playerItem
player.replaceCurrentItem(with: playerItem)
}
}
struct PlayerView: NSViewRepresentable {
@Binding var player: AVPlayer
func updateNSView(_ NSView: NSView, context: NSViewRepresentableContext<PlayerView>) {
guard let view = NSView as? AVPlayerView else {
debugPrint("unexpected view")
return
}
view.player = player
}
func makeNSView(context: Context) -> NSView {
return AVPlayerView(frame: .zero)
}
}
struct ContentView: View {
@ObservedObject var videoItem: VideoItem = VideoItem()
var body: some View {
VStack {
if videoItem.playerItem != nil {
PlayerView(player: $videoItem.player)
}
Button(action: {
let panel = NSOpenPanel()
panel.allowedFileTypes = [kUTTypeMovie as String]
DispatchQueue.main.async {
if panel.runModal() == .OK {
guard let url = panel.url else {
return
}
self.videoItem.open(url)
}
}
}) {
Text("Open")
}
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
在使用 "panel "对象选择文件时,这样做的效果非常好,但我无法解决将自己的 "url "值传递给videoItem.open()的简单变化。
我已经尝试过替换块。
let panel = NSOpenPanel()
panel.allowedFileTypes = [kUTTypeMovie as String]
DispatchQueue.main.async {
if panel.runModal() == .OK {
guard let url = panel.url else {
return
}
self.videoItem.open(url)
}
}
,使用URL(string:)或Bundle.main.url(forResource:, withExtension:)或其他选项定义我的 "url "值,但没有成功。应用程序编译和运行时没有出错,但它没有显示视频,只有一个占位图,表示没有找到文件。
我不明白从panel.url返回的 "url "值和我手动分配的值有什么区别。我使用.absoluteString检查了panel.url的内容,这与我手动分配的值完全一致。
我肯定遗漏了一些非常明显的东西,但我看不出是什么。拜托,谁能提供一些帮助?
这个问题的简单解决方案:确保视频文件被捆绑在目标应用程序中。
我以为我是这样做的,但显然不是,一个检查的方法(XCode 11)是。
在 "项目导航 "窗口中点击视频文件,然后:
在 "文件检查器 "窗口中勾选目标应用程序旁边的 "目标成员 "框。
就这样吧。这个答案的功劳属于 https:/github.comSergioEstevao。 他有一个针对SwiftUI应用的AVPlayer解决方案。https:/github.comSergioEstevaoSVEVideoUI。 这正是我想要的。