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

无法从照片库中的截图PNG文件获取创建日期求助

解决iOS截图PNG无法通过TIFF字典获取创建日期的问题

这个问题我之前也踩过坑!iOS系统通过Home键+电源键生成的PNG截图,确实不会像相机拍摄的JPG那样把创建日期写入TIFF元数据块,所以你通过CIImage读取TIFF字典自然拿不到数据。不过有两个更可靠的方案可以解决:

方案1:直接从PHAsset获取创建日期(推荐)

PHAsset本身就存储了资产的创建日期,这个值是系统相册数据库统一维护的,不管图片是JPG还是PNG(包括截图),都能正确返回。而且这种方式性能更好,不用加载整个图片数据,适合批量遍历。

示例代码:

// 配置获取选项,按创建日期倒序排列
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
// 获取所有图片资产
let imageAssets = PHAsset.fetchAssets(with: .image, options: fetchOptions)

// 遍历资产
imageAssets.enumerateObjects { asset, index, stop in
    // 直接读取PHAsset的creationDate属性
    if let creationDate = asset.creationDate {
        print("图片创建日期:\(creationDate)")
        // 这里处理你的业务逻辑
    }
}

方案2:通过PHAssetResource获取文件本身的元数据

如果你的场景必须从图片文件本身提取元数据(比如需要导出原始文件后读取),可以用PHAssetResource来获取完整的文件数据,再通过CGImageSource解析元数据。iOS截图的PNG文件会把日期存在其他元数据字段里,比如EXIF或者PNG专属的属性中。

示例代码:

let fetchOptions = PHFetchOptions()
let imageAssets = PHAsset.fetchAssets(with: .image, options: fetchOptions)

imageAssets.enumerateObjects { asset, index, stop in
    // 获取当前资产的资源对象
    let resources = PHAssetResource.assetResources(for: asset)
    guard let resource = resources.first else { return }
    
    // 请求资源数据
    let resourceManager = PHAssetResourceManager.default()
    resourceManager.requestData(for: resource, options: nil) { data, error in
        guard let data = data, error == nil else {
            print("获取资源数据失败:\(error?.localizedDescription ?? "未知错误")")
            return
        }
        
        // 解析图片元数据
        if let imageSource = CGImageSourceCreateWithData(data as CFData, nil) {
            let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [String: Any]
            
            // 尝试从PNG属性中读取日期
            if let pngProps = properties?[kCGImagePropertyPNGDictionary as String] as? [String: Any],
               let dateString = pngProps[kCGImagePropertyDateTimeOriginal as String] as? String {
                print("PNG元数据中的创建日期:\(dateString)")
            }
            // 尝试从EXIF属性中读取日期
            else if let exifProps = properties?[kCGImagePropertyExifDictionary as String] as? [String: Any],
                    let dateString = exifProps[kCGImagePropertyDateTimeOriginal as String] as? String {
                print("EXIF元数据中的创建日期:\(dateString)")
            }
        }
    }
}

关键说明

  • 为什么之前的方法无效?iOS系统截图是直接生成的PNG文件,系统不会像处理相机照片那样,把创建日期写入TIFF元数据块,所以通过CIImage.properties获取TIFF字典自然是空的。
  • 权限注意:确保你的App已经请求了照片库的读写权限(PHAuthorizationStatus.authorized),否则无法访问PHAsset的属性或资源数据。
  • 性能对比:方案1的性能远优于方案2,因为不需要加载整个图片文件,建议优先使用方案1。

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

火山引擎 最新活动