SwiftUI 4(iOS 16 Beta)如何显示从相册选择的视频?
解决方案
你的问题核心在于当前代码仅处理了图片转UIImage的渲染逻辑,视频的二进制数据无法通过UIImage解析,需要区分媒体类型并使用视频播放组件来处理。以下是修改后的完整实现及说明:
1. 新增必要框架导入
添加AVKit框架,用于视频播放功能:
import AVKit
2. 定义媒体类型枚举
创建枚举区分图片和视频,统一管理选中的媒体内容:
enum Media { case image(UIImage) case video(URL) }
3. 调整状态变量
将原data: Data?替换为存储媒体类型的状态变量:
@State var selectedMedia: Media?
4. 修改媒体加载逻辑
优先尝试加载图片类型,失败则加载视频的临时URL(系统会自动生成视频的临时文件路径):
5. 根据媒体类型渲染视图
在界面中根据selectedMedia的类型,分别显示图片或视频播放器。
修改后的完整代码:
import SwiftUI import PhotosUI import AVKit enum Media { case image(UIImage) case video(URL) } struct ContentView: View { @State var selectedItems: [PhotosPickerItem] = [] @State var selectedMedia: Media? var body: some View { VStack { // 根据选中的媒体类型渲染对应视图 if let media = selectedMedia { switch media { case .image(let uiImage): Image(uiImage: uiImage) .resizable() .scaledToFit() case .video(let videoURL): VideoPlayer(player: AVPlayer(url: videoURL)) .scaledToFit() .cornerRadius(8) } } PhotosPicker(selection: $selectedItems, maxSelectionCount: 1, matching: .any(of: [.images,.videos])) { Text("选择媒体") } .onChange(of: selectedItems) { newItems in guard let item = newItems.first else { selectedMedia = nil return } // 先尝试加载图片 item.loadTransferable(type: UIImage.self) { result in switch result { case .success(let image): if let image = image { selectedMedia = .image(image) return } // 图片加载失败,尝试加载视频URL fallthrough case .failure: item.loadTransferable(type: URL.self) { videoResult in switch videoResult { case .success(let videoURL): if let videoURL = videoURL { selectedMedia = .video(videoURL) } case .failure(let error): print("加载媒体失败: \(error.localizedDescription)") } } } } } } .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
关键说明:
VideoPlayer是SwiftUI 4新增的原生视图,直接传入AVPlayer实例即可实现视频播放,无需额外复杂配置。- 视频加载时,
PhotosPickerItem会返回系统生成的临时文件URL,可直接用于播放,无需手动处理文件存储。 - 先尝试加载图片再加载视频的逻辑,确保两种类型的媒体都能被正确识别和渲染。
内容的提问来源于stack exchange,提问作者user1591668
相关产品推荐
相关产品推荐

