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

将PHAsset转换为UIImage时出现非致命意外警告的问题

PHAsset转全尺寸UIImage时非致命警告的原因与解决办法

嘿,我帮你梳理下这个问题——你这段转PHAsset到全尺寸UIImage的代码逻辑其实没啥大问题,但控制台的非致命警告大概率是和PHImageRequestOptions的配置或者PHImageManager的回调特性有关,下面给你拆解原因和对应的解决思路:

常见警告原因

1. 图片尺寸适配提示

当你用PHImageManagerMaximumSize请求原图时,如果asset的原始尺寸特别大,系统可能会因为内存占用压力发出警告;另外contentMode: .aspectFit在处理超大图时,也可能触发系统对图片缩放的日志提示。

2. 异步回调重复调用提示

PHImageManager的requestImage方法有时候会多次回调:第一次返回低分辨率占位图,第二次才返回高清原图。如果你的警告和回调次数相关,比如提示重复处理图片,那就是这个原因。

3. iCloud资源加载状态提示

你开启了isNetworkAccessAllowed = true,如果asset是存放在iCloud上的资源,请求过程中可能会出现网络状态相关的警告,比如请求超时、缓存未命中的提示。

针对性解决办法

1. 优化图片请求配置

调整PHImageRequestOptions的参数,能有效避免大部分警告,修改后的代码如下:

func getOriginalAsset(asset: PHAsset, onComplete: @escaping (UIImage?, [AnyHashable: Any]?) -> ()) {
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    option.isNetworkAccessAllowed = true
    // 禁止自动调整尺寸,强制获取原始尺寸图片
    option.resizeMode = .none
    // 只返回高清图,跳过低分辨率占位图的回调
    option.deliveryMode = .highQualityFormat
    // 明确请求asset的原始版本,避免版本混淆
    option.version = .original
    
    manager.requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .default, options: option) { (image, info) in
        // 只处理最终的高清图回调,过滤占位图回调
        guard let info = info else {
            onComplete(image, nil)
            return
        }
        let isDegraded = info[PHImageResultIsDegradedKey] as? Bool ?? false
        if !isDegraded {
            onComplete(image, info)
        }
    }
}

这里的关键调整:

  • resizeMode = .none:强制获取原始尺寸,避免系统自动缩放带来的警告
  • deliveryMode = .highQualityFormat:跳过占位图,只返回一次高清图
  • version = .original:明确请求原始版本,消除版本相关的提示
  • 回调中判断PHImageResultIsDegradedKey,确保只处理最终的高清结果

2. 处理iCloud资源加载状态

如果警告和iCloud资源有关,可以在回调里监听状态,同时避免不必要的日志输出:

// 在回调逻辑中添加
let isInCloud = info[PHImageResultIsInCloudKey] as? Bool ?? false
if isInCloud {
    // 这里可以给用户显示“正在从iCloud加载图片”的提示,不用处理回调
    return
}

3. 内存优化(针对超大图警告)

如果是超大图导致的内存警告,可以先获取图片原始尺寸,再根据实际需求请求合适的尺寸,而不是直接请求PHImageManagerMaximumSize:

func getOriginalAsset(asset: PHAsset, onComplete: @escaping (UIImage?, [AnyHashable: Any]?) -> ()) {
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    option.isNetworkAccessAllowed = true
    
    // 先获取asset的原始尺寸
    manager.requestImageDataAndOrientation(for: asset, options: option) { data, _, orientation, info in
        guard let data = data, let imageSource = CGImageSourceCreateWithData(data as CFData, nil) else {
            onComplete(nil, info)
            return
        }
        let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [CFString: Any]
        let originalWidth = properties?[kCGImagePropertyPixelWidth] as? CGFloat ?? 0
        let originalHeight = properties?[kCGImagePropertyPixelHeight] as? CGFloat ?? 0
        
        // 根据实际需求设置目标尺寸,比如取屏幕宽高的2倍(适配Retina屏)
        let screenSize = UIScreen.main.bounds.size
        let targetSize = CGSize(width: screenSize.width * 2, height: screenSize.height * 2)
        
        // 再请求对应尺寸的图片
        manager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFit, options: option) { image, info in
            onComplete(image, info)
        }
    }
}

总的来说,这些警告大多是系统的提示性日志,不会影响功能,但通过调整请求配置和回调逻辑,既能消除警告,也能让图片加载的逻辑更健壮。

内容的提问来源于stack exchange,提问作者K.Wu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:18:45