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

iOS 15下全照片权限导致PHImageManager获取缩略图问题

问题:iOS 15下「所有照片」权限获取图片返回缩略图,「选中照片」则正常

当应用被授予「选中照片」权限时,以下代码能获取到预期的最大尺寸图片;但切换为「所有照片」权限后,返回的却是原图的缩略图。应用运行在iOS 15系统,未配置iCloud。

private func loadImage(assetId: String, done: @escaping (Image?) -> Void)  {
    
    let fetchResults: PHFetchResult<PHAsset> =
        PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: nil)

    guard let asset: PHAsset = fetchResults.firstObject else {
        return
    }

    let manager = PHImageManager()
    manager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize,
                            contentMode: .aspectFit, options: nil) { (uiImage, _) in
        if let uiImage = uiImage {
            done(Image(uiImage: uiImage))
        } else {
            done(nil)
        }
    }
}

原因分析

问题出在PHImageManager.requestImage的默认行为差异上:

  • 「选中照片」权限下,你指定的资产通常是本地直接可访问的,Photos框架能快速返回高清原图,不会触发占位图逻辑
  • 「所有照片」权限下,Photos框架默认会优先返回低分辨率缩略图作为快速占位,再异步加载高清图,但你的代码没有处理这种分阶段回调,只拿到了第一帧的缩略图

解决方案

通过配置PHImageRequestOptions强制获取高质量图片,同时处理可能的分阶段回调:

  1. 创建PHImageRequestOptions实例,设置deliveryMode为.highQualityFormat,跳过占位图直接加载高清图
  2. 可选设置resizeMode配合PHImageManagerMaximumSize确保获取原图尺寸
  3. 监听info字典中的PHImageResultIsDegradedKey,忽略临时缩略图回调,只处理最终高清图

修改后的代码如下:

private func loadImage(assetId: String, done: @escaping (Image?) -> Void)  {
    let fetchResults: PHFetchResult<PHAsset> =
        PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: nil)

    guard let asset = fetchResults.firstObject else {
        done(nil)
        return
    }

    let options = PHImageRequestOptions()
    // 强制只返回高质量图片,不返回占位缩略图
    options.deliveryMode = .highQualityFormat
    // 配合目标尺寸获取精确的原图大小
    options.resizeMode = .exact
    
    let manager = PHImageManager()
    manager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize,
                            contentMode: .aspectFit, options: options) { (uiImage, info) in
        // 过滤低质量的临时回调
        guard let isDegraded = info?[PHImageResultIsDegradedKey] as? Bool, !isDegraded else {
            return
        }
        done(uiImage.map { Image(uiImage: $0) })
    }
}

如果需要保留占位图优化体验,可以将deliveryMode设为默认的.opportunistic,通过PHImageResultIsDegradedKey区分临时和最终回调,先显示缩略图再替换为高清图。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:15:31