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
}

至于底層原理是為什么,我也不清楚,只是根據報錯信息,蒙著改了。如果有了解這塊的朋友,歡迎大家留言討論。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。