You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何从UIImagePickerController获取媒体文件的拍摄创建日期

Swift中从UIImagePickerController回调获取媒体拍摄日期的实现方案

前置依赖

  • 导入Photos框架,所有资源日期都通过PHAsset对象获取,适配图片、视频两类媒体
  • 提前在Info.plist中配置对应权限描述:
    • 相册读取:NSPhotoLibraryUsageDescription
    • 相机权限:NSCameraUsageDescription
    • 相册写入(相机拍摄后存入场景需要):NSPhotoLibraryAddUsageDescription
  • 调用功能前先通过PHPhotoLibrary.requestAuthorization(for:handler:)申请对应相册权限

核心实现逻辑

在UIImagePickerControllerDelegate的imagePickerController(_:didFinishPickingMediaWithInfo:)回调中,根据sourceType分两种场景处理:

1. sourceType为.photoLibrary(从相册选择)

从系统返回的info字典中可直接拿到对应资源的PHAsset对象,其creationDate属性就是媒体的拍摄日期,示例代码如下:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    picker.dismiss(animated: true)
    
    guard picker.sourceType == .photoLibrary else { return }
    // 直接取系统返回的PHAsset
    guard let asset = info[.phAsset] as? PHAsset else {
        print("获取相册资源失败")
        return
    }
    // 读取拍摄日期
    if let shootDate = asset.creationDate {
        // 后续业务逻辑处理shootDate即可
        print("媒体拍摄日期:\(shootDate)")
    }
}

2. sourceType为.camera(相机实时拍摄)

相机刚拍摄的媒体默认不会存入相册,info字典中没有直接返回PHAsset,可以选择两种方式获取日期:

方式A:拍摄后先存入相册再读取日期(推荐,适配图片/视频,逻辑简单)

import MobileCoreServices // 需要引入该框架判断媒体类型

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    picker.dismiss(animated: true)
    
    guard picker.sourceType == .camera else { return }
    let mediaType = info[.mediaType] as! String
    
    PHPhotoLibrary.shared().performChanges {
        let createRequest = PHAssetCreationRequest.forAsset()
        // 区分图片和视频写入
        if mediaType == kUTTypeImage as String, let image = info[.originalImage] as? UIImage {
            createRequest.addResource(with: .photo, image: image, options: nil)
        } else if mediaType == kUTTypeMovie as String, let videoUrl = info[.mediaURL] as? URL {
            createRequest.addResource(with: .video, fileURL: videoUrl, options: nil)
        }
    } completionHandler: { success, error in
        guard success, error == nil else { return }
        // 拉取最新存入的资源
        let fetchOpt = PHFetchOptions()
        fetchOpt.sortDescriptors = [.init(key: "creationDate", ascending: false)]
        fetchOpt.fetchLimit = 1
        let fetchResult = PHAsset.fetchAssets(with: fetchOpt)
        guard let asset = fetchResult.firstObject, let shootDate = asset.creationDate else { return }
        DispatchQueue.main.async {
            // 回到主线程处理业务逻辑
            print("拍摄日期:\(shootDate)")
        }
    }
}

方式B:不存入相册,直接从媒体元数据提取

如果不需要保留拍摄的媒体到相册,可以直接读取EXIF(图片)或视频元数据中的拍摄日期,以图片为例:

if let imageUrl = info[.imageURL] as? URL, 
   let imageSource = CGImageSourceCreateWithURL(imageUrl as CFURL, nil),
   let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [String: Any],
   let exif = properties[kCGImagePropertyExifDictionary as String] as? [String: Any],
   let dateStr = exif[kCGImagePropertyExifDateTimeOriginal as String] as? String {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy:MM:dd HH:mm:ss"
    if let shootDate = formatter.date(from: dateStr) {
        print("EXIF提取的拍摄日期:\(shootDate)")
    }
}

注意事项

  • iOS版本适配:UIImagePickerController.InfoKey.phAsset仅支持iOS 11及以上版本,如需兼容更低版本,可通过info[.referenceURL]获取资源链接后调用PHAsset.fetchAssets(withALAssetURLs:options:)获取PHAsset
  • 时区处理:PHAsset.creationDate返回的是UTC时区的Date对象,展示给用户时需要转换为当地时区
  • 空值处理:部分截图、网络保存的图片可能没有拍摄日期,需要做好creationDate为空的兜底逻辑

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 14:24:00