我是乐器的新手,但我之前成功找到了泄漏。这一次,不是这样 - 每次调用此代码时都会有34MB的泄漏! 我已经尝试发布下面的所有相关代码,同时剪掉DDLogging等内容......
首先,仪器屏幕显示问题。请注意,我尝试模拟内存警告并等待一段时间,没有任何变化 - 这个内存被永久吃掉。
PhotoManager.m:
- (void)saveImage:(UIImage*)unimage completionBlock:(void(^)(BOOL success, NSError *error))completionBlock {
__weak typeof(self) weakSelf = self;
dispatch_block_t work = ^{
__block UIImage* image = [[AirprintCollagePrinter singleton] fixRotation:unimage];
// if trial mode, always downsize and watermark image
if( [PurchaseHelper singleton].getPurchaseLevel == PurchaseLevelTrial ) {
dispatch_sync(_photoManagerQueue, ^{
if( image.size.height > 1800 || image.size.width > 1200 ) {
image = [[AirprintCollagePrinter singleton] fitImage:image scaledToFillSize:CGSizeMake(1200, 1800)];
}
image = [weakSelf imageWithWatermark:image withWatermark:_watermarkImage];
});
}
<snip>
};
if( [[NSThread currentThread] isMainThread] )
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), work);
else
work();
}
从Instruments screencap中你可以看到AirprintCollagePrinter:fitImage是我的代码在跟踪中的最后一部分,所以这里有:
AirprintCollagePrinter.m:
- (UIImage *)fitImage:(UIImage *)image scaledToFillSize:(CGSize)size {
// do not upscale
@autoreleasepool {
if( image.size.width <= size.width && image.size.height <= size.height )
return image;
CGFloat scale = MIN(size.width/image.size.width, size.height/image.size.height);
CGFloat width = image.size.width * scale;
CGFloat height = image.size.height * scale;
CGRect imageRect = CGRectMake(0,
0,
width,
height);
UIGraphicsBeginImageContextWithOptions(size, YES, 0);
[image drawInRect:imageRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
}
...我记得要结束我的图片上下文并将其包装在autoreleasepool中......我错过了什么?
答案 0 :(得分:1)
想出来。从上面的代码中,它是一个二级thead(实际上是一个NSOperation),它调用了PhotoManager:saveImage,它就是这样做的:
while ( true ) {
// do work
[PhotoManager singleton] saveImage:xyz];
[NSThread sleepForTimeInterval:0.5];
}
问题在于虽然辅助线程的main()正在使用@autoreleasepool,但是该池永远没有时间流失,因为线程总是处于休眠或工作状态。
解决方案是使用这样的另一个@autorelease池,在其外面进行睡眠:
while ( true ) {
@autoreleasepool {
// do work
[PhotoManager singleton] saveImage:xyz];
}
[NSThread sleepForTimeInterval:0.5];
}
答案 1 :(得分:0)
请改用CGImageRef。像这样:
CGImageRef imageRef = image.CGImage;
CGColorSpaceRef colorspaceRef =CGColorSpaceCreateDeviceRGB();
CFAutorelease(colorspaceRef);
size_t width = itemSize.width;
size_t height = itemSize.height;
size_t bytesPerRow = kBytesPerPixel * width;
CGContextRef context = CGBitmapContextCreate(NULL,
width,
height,
kBitsPerComponent,
bytesPerRow,
colorspaceRef,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
// Draw the image into the context and retrieve the new bitmap image without alpha
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGImageRef imageRefWithoutAlpha = CGBitmapContextCreateImage(context);
image = [UIImage imageWithCGImage:imageRefWithoutAlpha scale:image.scale orientation:image.imageOrientation];
CGContextRelease(context);
CGImageRelease(imageRefWithoutAlpha);