CGDataProviderRef释放回调未触发:CGBitmap像素缓冲区无法释放
问题分析与解决
核心原因
你猜的没错,done_callback始终不执行的关键原因就是你创建的Core Graphics对象没有被正确释放。Core Graphics采用手动引用计数机制,你创建的CGImageRef、CGDataProviderRef、CGColorSpaceRef都会持有资源引用,只要这些对象没被销毁,系统就不会触发数据提供者的回调来释放像素缓冲区。
具体修复步骤
释放创建的中间CG对象
CGImageCreate会自动持有传入的CGDataProviderRef和CGColorSpaceRef的引用,所以在创建完CGImage后,你可以立即释放这两个对象,避免不必要的内存占用:CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, width * height * 4, done_callback); CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; CGImageRef image = CGImageCreate(width, height, 8, 32, 4 * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); // 释放不再需要的provider和colorSpace CGDataProviderRelease(provider); CGColorSpaceRelease(colorSpaceRef); return image;调用方必须释放返回的CGImageRef
调用SVG_to_CGImage的代码,在使用完返回的CGImageRef后,必须手动调用CGImageRelease()来释放它。只有当CGImage被销毁时,它持有的CGDataProvider才会被释放,进而触发done_callback:CGImageRef svgImage = SVG_to_CGImage(svgContent, 200, 200); // 这里做渲染、转换UIImage等操作 CGImageRelease(svgImage); // 执行这行后,done_callback才会被调用
额外优化(ARC环境下)
如果是在Objective-C的ARC环境中使用,可以把CGImageRef包装成UIImage,让ARC自动管理内存:
CGImageRef svgImage = SVG_to_CGImage(svgContent, 200, 200); UIImage *uiImage = [UIImage imageWithCGImage:svgImage]; CGImageRelease(svgImage); // 这里手动释放CGImage,UIImage会持有内部资源 // 当uiImage被ARC销毁时,会自动释放对应的CG资源,触发done_callback
内容的提问来源于stack exchange,提问作者Charlie Skilbeck
相关产品推荐
相关产品推荐

