将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

