iOS 17中-[UIImage drawInRect:blendMode:alpha:]崩溃问题咨询
iOS 17.0下HEIF图片解码崩溃问题排查与修复
这段代码在iOS 17.0之前运行正常,但在iOS 17.0环境下出现崩溃,以下是崩溃调用栈:
0 VideoToolbox 0x00000001b145025c ___VTDecompressionSessionRemote_DecodeTile_block_invoke_2 :60 (in VideoToolbox) 1 libdispatch.dylib 0x00000001a8a8b300 __dispatch_client_callout :20 (in libdispatch.dylib) 2 libdispatch.dylib 0x00000001a8a9a6b4 __dispatch_lane_barrier_sync_invoke_and_complete :56 (in libdispatch.dylib) 3 VideoToolbox 0x00000001b14500e0 _VTDecompressionSessionRemote_DecodeTile :696 (in VideoToolbox) 4 CMPhoto 0x00000001c4f9cb70 _VTTileDecompressionPluginClass_decode :376 (in CMPhoto) 5 CMPhoto 0x00000001c4fa2974 __decodeItem :6008 (in CMPhoto) 6 CMPhoto 0x00000001c4f9278c __applyDecodeStrategy :396 (in CMPhoto) 7 CMPhoto 0x00000001c4ff755c __decodeImage :452 (in CMPhoto) 8 CMPhoto 0x00000001c4ff3418 __createImageForIndex :472 (in CMPhoto) 9 CMPhoto 0x00000001c4fae3b0 _CMPhotoDecompressionContainerCreateImageForIndex :280 (in CMPhoto) 10 ImageIO 0x00000001a696fe74 __ZN14HEIFReadPlugin20copyImageBlockSetImpEP7InfoRecP15CGImageProvider6CGRect6CGSizePK14__CFDictionary :2208 (in ImageIO) 11 ImageIO 0x00000001a69722dc __ZN14HEIFReadPlugin14decodeImageImpEP18IIODecodeParameter12IIOImageTypePP11__IOSurfacePP10__CVBufferPP15CGImageBlockSet :616 (in ImageIO) 12 ImageIO 0x00000001a67dd55c __ZN13IIOReadPlugin15callDecodeImageEP18IIODecodeParameter12IIOImageTypePP11__IOSurfacePP10__CVBufferPP15CGImageBlockSet :800 (in ImageIO) 13 ImageIO 0x00000001a67dce90 __ZN10IIO_Reader21CopyImageBlockSetProcEPvP15CGImageProvider6CGRect6CGSizePK14__CFDictionary :688 (in ImageIO) 14 ImageIO 0x00000001a67dcaf8 __ZN20IIOImageProviderInfo28copyImageBlockSetWithOptionsEP15CGImageProvider6CGRect6CGSizePK14__CFDictionary :744 (in ImageIO) 15 ImageIO 0x00000001a67dc728 __ZN20IIOImageProviderInfo28CopyImageBlockSetWithOptionsEPvP15CGImageProvider6CGRect6CGSizePK14__CFDictionary :804 (in ImageIO) 16 CoreGraphics 0x00000001a2726dd8 _imageProvider_retain_data :92 (in CoreGraphics) 17 CoreGraphics 0x00000001a2711098 _CGDataProviderRetainData :80 (in CoreGraphics) 18 CoreGraphics 0x00000001a27110e0 _provider_for_destination_retain_data :28 (in CoreGraphics) 19 CoreGraphics 0x00000001a2711098 _CGDataProviderRetainData :80 (in CoreGraphics) 20 CoreGraphics 0x00000001a2710d64 _CGAccessSessionCreate :124 (in CoreGraphics) 21 CoreGraphics 0x00000001a270dfec _img_data_lock :2400 (in CoreGraphics) 22 CoreGraphics 0x00000001a270d640 _CGSImageDataLock :1324 (in CoreGraphics) 23 CoreGraphics 0x00000001a2718a54 _ripc_AcquireRIPImageData :848 (in CoreGraphics) 24 CoreGraphics 0x00000001a2718290 _ripc_DrawImage :832 (in CoreGraphics) 25 CoreGraphics 0x00000001a2717dc8 _CGContextDrawImageWithOptions :1120 (in CoreGraphics) 26 UIKitCore 0x00000001a2e47b00 -[UIImage drawInRect:blendMode:alpha:] :1072 (in UIKitCore)
问题分析
从调用栈可以看出,崩溃发生在VideoToolbox的分块解码逻辑中:流程从-[UIImage drawInRect:blendMode:alpha:]触发,经CoreGraphics、ImageIO,最终调用CMPhoto的HEIF解码模块,再调用VideoToolbox远程解码会话时崩溃。结合iOS 17.0之前无此问题的情况,这属于iOS 17.0系统在HEIF图片分块解码上的兼容性bug。
修复方案
方案一:转换图片格式绕过HEIF解码
将HEIF图片转换为PNG或JPEG格式后再处理,直接避开系统的HEIF解码逻辑:
// iOS 12+推荐使用新API UIImage *heifImage = [UIImage imageNamed:@"test.heic"]; NSData *pngData = heifImage.pngData(); UIImage *pngImage = [UIImage imageWithData:pngData]; // 后续使用pngImage进行绘制操作
方案二:修改图片绘制逻辑
如果必须使用HEIF格式,尝试避免直接调用drawInRect:blendMode:alpha::
- 优先使用
UIImageView直接显示图片,让系统处理绘制逻辑; - 若需手动绘制,将绘制操作放到异步队列执行,避免主线程同步触发分块解码:
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ UIImage *processedImage = [self processOriginalImage:originalHeifImage]; dispatch_async(dispatch_get_main_queue(), ^{ [processedImage drawInRect:targetRect blendMode:kCGBlendModeNormal alpha:1.0]; }); });
方案三:升级系统版本
苹果通常会在iOS小版本更新中修复这类系统级bug,测试iOS 17.1及以上版本,若bug已修复,引导用户升级系统。
方案四:手动配置ImageIO解码参数
使用ImageIO API手动解码HEIF图片,添加缓存参数避免分块解码:
NSData *heifData = [NSData dataWithContentsOfFile:@"test.heic"]; NSDictionary *decodeOptions = @{ (__bridge NSString *)kCGImageSourceShouldCacheImmediately : @YES, (__bridge NSString *)kCGImageSourceCreateThumbnailFromImageAlways : @NO }; CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)heifData, (__bridge CFDictionaryRef)decodeOptions); CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)decodeOptions); UIImage *image = [UIImage imageWithCGImage:cgImage]; // 释放资源 CGImageRelease(cgImage); CFRelease(source);
内容的提问来源于stack exchange,提问作者Albert
相关产品推荐
相关产品推荐

