为何设置UIImagePicker.mediaTypes为[kUTTypeMovie]会包含带Bounce/Loop效果的Live Photos?
解决UIImagePicker选取视频时包含带Bounce/Loop特效Live Photo的问题
嘿,这个坑我之前踩过!其实问题出在苹果对带特效的Live Photo的处理上——当你给Live Photo设置Bounce或Loop效果时,系统会自动生成一个对应的小型视频轨道关联到这个图片资产里,导致UIImagePicker的kUTTypeMovie过滤规则把它误判成视频了。而切换到Live或Long Exposure效果时,这个关联的视频轨道会被移除,所以就不会被列出来了。
下面给你两个可行的解决方案,根据你的iOS版本支持需求来选:
方案1:兼容iOS 13及以下,手动过滤带特效的Live Photo
我们可以借助Photos框架,在用户选择资产后,检查对应的PHAsset属性,把带Bounce/Loop特效的Live Photo排除掉:
首先导入Photos框架,然后在UIImagePicker的回调里处理:
import Photos func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { picker.dismiss(animated: true) // 先获取选中的媒体URL guard let mediaURL = info[.mediaURL] as? URL else { print("无法获取媒体URL") return } // 通过URL找到对应的PHAsset let fetchOptions = PHFetchOptions() let fetchResult = PHAsset.fetchAssets(withALAssetURLs: [mediaURL], options: fetchOptions) guard let targetAsset = fetchResult.firstObject else { // 正常处理视频 handleSelectedVideo(url: mediaURL) return } // 判断是否是带Bounce/Loop特效的Live Photo let isFilteredLivePhoto = targetAsset.mediaType == .image && targetAsset.mediaSubtypes.contains(.photoLive) && (targetAsset.effectivePlaybackStyle == .loop || targetAsset.effectivePlaybackStyle == .bounce) if isFilteredLivePhoto { // 这里可以提示用户,或者直接跳过处理 print("这是带特效的Live Photo,不是视频哦") return } // 处理真正的视频文件 handleSelectedVideo(url: mediaURL) } // 自定义的视频处理方法 func handleSelectedVideo(url: URL) { // 你的视频逻辑代码 }
核心是effectivePlaybackStyle这个属性,它能直接获取Live Photo当前的播放特效类型,精准过滤掉我们不需要的资产。
方案2:iOS 14+推荐,用PHPicker替代UIImagePicker
苹果在iOS14推出的PHPicker是更现代的媒体选择器,它的过滤逻辑更精准,不需要手动处理就能自动排除带特效的Live Photo:
先导入PhotosUI框架,然后实现选择器:
import PhotosUI func showVideoPicker() { var pickerConfig = PHPickerConfiguration() // 设置只允许选择视频 pickerConfig.filter = .videos pickerConfig.selectionLimit = 1 // 可根据需求调整选择数量 let picker = PHPickerViewController(configuration: pickerConfig) picker.delegate = self present(picker, animated: true) } // PHPicker的回调方法 func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) guard let selectedResult = results.first else { return } // 加载选中的视频URL selectedResult.itemProvider.loadObject(ofClass: URL.self) { [weak self] result, error in guard let self = self, let videoURL = result as? URL, error == nil else { print("加载视频失败") return } // 处理视频 self.handleSelectedVideo(url: videoURL) } }
PHPicker会自动把带Bounce/Loop特效的Live Photo归类为图片资产,不会被.videos过滤器选中,用起来更省心,而且现在iOS14及以上的用户占比很高,推荐优先采用这个方案。
内容的提问来源于stack exchange,提问作者Lance Samaria
相关产品推荐
相关产品推荐

