PHImageManager requestImageForAsset,在 iOS18 下崩溃

Q:

iOS18 发布之后,收到了很多拉起相册时的崩溃客诉。堆栈日志如下:

#0 Thread
NSInternalInconsistencyException
opportunisticDegradedImagesToReturn cannot be zero.
解析原始
0
CoreFoundation
___exceptionPreprocess + 164

6
Photos
-[PHImageManager requestImageForAsset:targetSize:contentMode:options:resultHandler:] + 172

......(略)

crash 位置还是很清晰的,但是原因不清晰啊,没见过这个报错,网上也没搜到有效信息,也没听说 iOS18 后,相册哪里要做额外的兼容。

我们项目中的这块代码实现,简略如下:

PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc] initWithImageRequestOptions:options];
imageRequestOptions.synchronous = YES;
imageRequestOptions.networkAccessAllowed = YES;
imageRequestOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
imageRequestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;

[[PHImageManager defaultManager] requestImageForAsset:phAsset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:imageRequestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
   // TODO: image something
}];

A:

从报错信息看,主要是说 opportunisticDegradedImages 这个东西,不能是 zero,那 opportunistic 和 degraded 这两个关键词是什么意思呢?

opportunistic:

指的是 PHImageRequestOptions 对象 deliveryMode 属性的值,他表示请求的图像质量和交付优先级。我用的默认值 PHImageRequestOptionsDeliveryModeOpportunistic,表示平衡下图像质量和响应速度,也就是报错这个关键词。详情可参考这篇文章:链接

@property (nonatomic, assign) PHImageRequestOptionsDeliveryMode deliveryMode; // delivery mode. Defaults to PHImageRequestOptionsDeliveryModeOpportunistic

typedef NS_ENUM(NSInteger, PHImageRequestOptionsDeliveryMode) {
    PHImageRequestOptionsDeliveryModeOpportunistic = 0, // client may get several image results when the call is asynchronous or will get one result when the call is synchronous
    PHImageRequestOptionsDeliveryModeHighQualityFormat = 1, // client will get one result only and it will be as asked or better than asked
    PHImageRequestOptionsDeliveryModeFastFormat = 2 // client will get one result only and it may be degraded
};
degraded:

这单词是降级的意思,翻了翻 PHImageRequestOptions 的 API,allowSecondaryDegradedImage 属性看起来比较接近,他表示除了初始的降级结果之外,如果条件允许,是否还返回一个额外的降级结果。
这是 iOS17 新增的 API,官方也并没太多的说明介绍 AppleDevelopDoc链接

@property (nonatomic) BOOL allowSecondaryDegradedImage API_AVAILABLE(macos(14), ios(17), tvos(17)); // in addition to the initial degraded result, an additional degraded result will be returned if conditions permit
fix 方案:

于是尝试把 allowSecondaryDegradedImage 设为 YES 看看,然后就 OK 了。。。就不崩了。。。。

if (@available(iOS 17, *)) {
    imageRequestOptions.allowSecondaryDegradedImage = YES;
} else {
    // Fallback on earlier versions
}

至于底层原理是为什么,我也不清楚,只是根据报错信息,蒙着改了。如果有了解这块的朋友,欢迎大家留言讨论。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。