SwiftUI 4.0中如何通过PhotosPickerItem的item identifier加载选中视频
解决SwiftUI 4 PhotosPicker无法处理视频的问题
你当前的代码用loadTransferable(type: Data.self)加载视频,这种方式不仅内存占用高,而且没法直接对接AVPlayer。另外,PhotosPickerItem的itemIdentifier是系统内部标识,不能直接用来构造可访问的视频URL,正确的做法是通过加载视频的本地临时URL来实现播放。
核心修改点
- 替换加载类型为URL:视频文件体积通常较大,加载成Data会占用大量内存,直接加载为本地URL更高效,也符合AVPlayer的使用需求。
- 更新AVPlayer实例:获取到视频URL后,创建新的AVPlayer并赋值给@State变量,触发UI自动更新。
- 优化错误处理:避免使用
fatalError导致崩溃,改用打印错误信息的方式排查问题。
修改后的完整代码
import SwiftUI import PhotosUI import AVKit struct PlayVideoView: View { @State private var selectedItem: [PhotosPickerItem] = [] @State private var player: AVPlayer? = AVPlayer(url: URL(string: "https://swiftanytime-content.s3.ap-south-1.amazonaws.com/SwiftUI-Beginner/Video-Player/iMacAdvertisement.mp4")!) var body: some View { PhotosPicker(selection: $selectedItem, maxSelectionCount: 1, matching: .any(of: [.images,.videos])) { Image(systemName: "photo") .resizable() .foregroundColor(.blue) .frame(width: 24, height: 24) .padding(.top, 5.0) } .onChange(of: selectedItem) { newMedia in Task { guard let item = selectedItem.first else { return } // 加载视频的本地临时URL do { if let videoURL = try await item.loadTransferable(type: URL.self) { // 创建新的AVPlayer实例并赋值 player = AVPlayer(url: videoURL) // 可选:自动播放选中的视频 player?.play() } else { print("无法获取视频URL") } } catch { print("加载视频失败: \(error.localizedDescription)") } } } // 处理player为空的情况 if let player = player { VideoPlayer(player: player) .frame(width: 400, height: 300, alignment: .center) } else { Text("未选中视频") .frame(width: 400, height: 300) } } } struct PlayVideoView_Previews: PreviewProvider { static var previews: some View { PlayVideoView() } }
补充说明
- 临时URL生命周期:通过
loadTransferable(type: URL.self)获取的URL是系统沙盒内的临时文件路径,只要你持有该URL并在使用,系统会自动保留文件,无需手动清理。 - 视频格式支持:代码中
matching: .any(of: [.images,.videos])已经包含所有系统支持的视频类型(如mov、mp4等),无需额外配置。 - 权限配置:确保在
Info.plist中添加NSPhotoLibraryUsageDescription权限描述,否则无法访问系统相册内容。
内容的提问来源于stack exchange,提问作者user1591668
相关产品推荐
相关产品推荐

