You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

相册选择MOV文件无响应及多格式文件支持技术求助

解决UIImagePickerController选择MOV无响应问题,并支持多格式文件选择

咱们先搞定你当前遇到的MOV文件无响应问题,再扩展实现你需要的全格式文件支持需求。

一、排查并修复MOV选择无响应问题

你提到iPhone拍摄的MOV正常,但保存到手机的MOV会导致界面卡住、回调不触发,大概率是这两个核心原因:

  1. 主线程被阻塞:如果在didFinishPickingMediaWithInfo的闭包里处理MOV文件时做了解码、大文件拷贝这类耗时操作,会直接卡死主线程,导致取消按钮和回调都失效;
  2. 媒体类型配置不明确:未指定UIImagePickerControllermediaTypes,部分非系统拍摄的MOV可能因UTI识别异常无法触发回调。

调整后的修复代码

把耗时操作移到后台线程,避免阻塞主线程,同时明确配置支持的媒体类型:

// 修复后的picker回调
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    dismiss(animated: true) {
        guard let mediaType = info[.mediaType] as? String else { return }
        
        if mediaType == kUTTypeImage as String, let pickedImage = info[.originalImage] as? UIImage {
            // 图片处理逻辑移到后台
            DispatchQueue.global().async {
                // 这里写你的图片处理代码
                DispatchQueue.main.async {
                    self.updateProgress()
                    self.collection.reloadData()
                }
            }
        } else if mediaType == kUTTypeMovie as String {
            // MOV文件处理必须放后台线程
            DispatchQueue.global().async {
                guard let movieURL = info[.mediaURL] as? URL else { return }
                // 这里写你的MOV文件处理逻辑(比如拷贝、转码)
                DispatchQueue.main.async {
                    self.updateProgress()
                    self.collection.reloadData()
                }
            }
        }
    }
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
    dismiss(animated: true, completion: nil)
}

// 初始化picker时明确指定支持的媒体类型
let iPicker = UIImagePickerController()
iPicker.delegate = self
iPicker.mediaTypes = [kUTTypeImage as String, kUTTypeMovie as String]

二、扩展支持所有需要的文件格式

注意:UIImagePickerController仅支持图片和视频类文件,你需要的zip、doc、pdf等文档格式,必须使用系统提供的UIDocumentPickerViewController来实现,这是处理全格式文件选择的标准方案。

1. 初始化文档选择器

func presentDocumentPicker() {
    // 定义你需要支持的文件UTI列表(对应你的目标格式)
    let supportedUTIs = [
        "com.pkware.zip-archive", // zip
        "com.microsoft.word.doc", // doc
        "com.microsoft.outlook.msg", // msg
        "public.jpeg", // jpg/jpeg
        "public.avi", // avi
        "com.microsoft.powerpoint.pps", // pps
        "public.gif", // gif
        "public.png", // png
        "com.microsoft.excel.xls", // xls
        "public.comma-separated-values-text", // csv
        "com.adobe.pdf", // pdf
        "public.plain-text", // txt
        "com.microsoft.powerpoint.ppt", // ppt
        "public.tiff", // tiff/tif
        "com.autodesk.dwg" // dwg
    ]
    
    let documentPicker = UIDocumentPickerViewController(
        forOpeningContentTypes: supportedUTIs.compactMap { UTType($0) }
    )
    documentPicker.delegate = self
    documentPicker.allowsMultipleSelection = false // 根据需求设置是否允许多选
    present(documentPicker, animated: true)
}

2. 实现文档选择器代理方法

extension YourViewController: UIDocumentPickerDelegate {
    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        guard let fileURL = urls.first else { return }
        
        // 文档选择器返回的是临时沙盒URL,需要拷贝到APP自己的目录保存
        DispatchQueue.global().async {
            let destinationDir = self.getAppDocumentDirectory()
            let destinationURL = destinationDir.appendingPathComponent(fileURL.lastPathComponent)
            
            do {
                // 先删除已存在的同名文件
                if FileManager.default.fileExists(atPath: destinationURL.path) {
                    try FileManager.default.removeItem(at: destinationURL)
                }
                // 拷贝文件到本地
                try FileManager.default.copyItem(at: fileURL, to: destinationURL)
                
                // 根据文件类型执行对应处理逻辑
                self.handleFile(at: destinationURL)
                
                DispatchQueue.main.async {
                    self.updateProgress()
                    self.collection.reloadData()
                }
            } catch {
                print("文件处理失败:\(error.localizedDescription)")
                DispatchQueue.main.async {
                    // 这里可以给用户弹出错误提示
                }
            }
        }
    }
    
    func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        dismiss(animated: true, completion: nil)
    }
    
    // 辅助方法:获取APP的文档目录
    private func getAppDocumentDirectory() -> URL {
        return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    }
    
    // 根据文件后缀处理不同类型的文件
    private func handleFile(at url: URL) {
        let fileExt = url.pathExtension.lowercased()
        switch fileExt {
        case "jpg", "jpeg", "png", "gif", "tiff", "tif":
            // 处理图片逻辑
            if let image = UIImage(contentsOfFile: url.path) {
                // do something with image
            }
        case "avi", "mov":
            // 处理视频逻辑
            // do something with video URL
        case "doc", "xls", "ppt", "pps", "pdf", "txt", "csv", "zip", "msg", "dwg":
            // 处理文档/压缩包等逻辑
            // do something with document URL
        default:
            break
        }
    }
}

总结

  1. 先通过后台线程处理耗时操作+明确配置媒体类型修复当前MOV选择无响应的问题;
  2. 迁移到UIDocumentPickerViewController实现全格式支持,这是系统推荐的文档类文件选择方案,既能覆盖你所有目标格式,也能避免UIImagePicker的功能局限性。

内容的提问来源于stack exchange,提问作者user2363025

火山引擎 最新活动