我正在创建的 iPad 应用程序必须能够为之前在我的应用程序中生成的 4096x2992 图像创建图块。
4096x2992 图像不是很复杂(我正在测试的内容),当以 png 格式写入文件时大约为 600kb ...
在模拟器上,这段代码似乎工作正常,但是当我在更严格的内存条件下(在我的 iPad 上)运行应用程序时,进程退出,因为它内存不足......
我一直在应用程序中使用相同的代码,以前工作正常(但是只为 3072x2244 图像创建图块)......
要么我必须做一些愚蠢的错误,要么我的@autoreleasepool 没有按应有的方式工作(我想我提到我使用 ARC)......在仪器中运行时,我只能看到使用的内存攀升到 ~500mb然后崩溃!
我已经分析了代码,但没有发现与我的应用程序的这一部分相关的单个内存泄漏,所以我真的很困惑为什么这会在我身上崩溃......
只是关于如何调用我的函数的一点历史,所以你知道发生了什么......该应用程序使用 CoreGraphics 渲染一个 UIView (4096x2992),其中包含一些 UIImageView,然后它将 UIImage 引用发送到我的函数buildFromImage:
(如下)开始切割向上/调整图像大小以创建我的文件...
这是代码...内存问题是在...buildFromImage:
下的主循环中建立的NSLog(@"LOG ------------> Begin tile loop ");
-(void)buildFromImage:(UIImage *)__image {
NSLog(@"LOG ------------> Begin Build ");
//if the __image is over 4096 width of 2992 height then we must resize it! (stop crashes ect)
if (__image.size.width > __image.size.height) {
if (__image.size.width > 4096) {
__image = [self resizeImage:__image toSize:CGSizeMake(4096, (__image.size.height * 4096 / __image.size.width))];
}
} else {
if (__image.size.height > 2992) {
__image = [self resizeImage:__image toSize:CGSizeMake((__image.size.width * 2992 / __image.size.height), 2992)];
}
}
//create preview image (if landscape, no more than 748 high... if portrait, no more than 1004 high) must keep scale
NSString *temp_archive_store = [[NSString alloc] initWithFormat:@"%@/%i-temp_imgdat.zip",NSTemporaryDirectory(),arc4random()];
NSString *temp_tile_store = [[NSString alloc] initWithFormat:@"%@/%i-temp_tilestore/",NSTemporaryDirectory(),arc4random()];
//create the temp dir for the tile store
[[NSFileManager defaultManager] createDirectoryAtPath:temp_tile_store withIntermediateDirectories:YES attributes:nil error:nil];
//create each tile and add it to the compressor once its made
//size of tile
CGSize tile_size = CGSizeMake(256, 256);
//the scales that we will be generating the tiles too
NSMutableArray *scales = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:1000],[NSNumber numberWithInt:500],[NSNumber numberWithInt:250],[NSNumber numberWithInt:125], nil]; //scales to loop round over
NSLog(@"LOG ------------> Begin tile loop ");
@autoreleasepool {
//loop through the scales
for (NSNumber *scale in scales) {
//scale the image
UIImage *imageForScale = [self resizedImage:__image scale:[scale intValue]];
//calculate number of rows...
float rows = ceil(imageForScale.size.height/tile_size.height);
//calulate number of collumns
float cols = ceil(imageForScale.size.width/tile_size.width);
//loop through rows and cols
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
NSLog(@"LOG ------> Creating Tile (%i,%i,%i)",col,row,[scale intValue]);
//build name for tile...
NSString *tile_name = [NSString stringWithFormat:@"%@_%i_%i_%i.png",@"image",[scale intValue],col,row];
@autoreleasepool {
//build tile for this coordinate
UIImage *tile = [self tileForRow:row column:col size:tile_size image:imageForScale];
//convert image to png data
NSData *tile_data = UIImagePNGRepresentation(tile);
[tile_data writeToFile:[NSString stringWithFormat:@"%@%@",temp_tile_store,tile_name] atomically:YES];
}
}
}
}
}
}
这也是我的调整大小/裁剪功能,因为这些也可能导致问题..
-(UIImage *)resizeImage:(UIImage *)inImage toSize:(CGSize)scale {
@autoreleasepool {
CGImageRef inImageRef = [inImage CGImage];
CGColorSpaceRef clrRf = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(NULL, ceil(scale.width), ceil(scale.height), CGImageGetBitsPerComponent(inImageRef), CGImageGetBitsPerPixel(inImageRef)*ceil(scale.width), clrRf, kCGImageAlphaPremultipliedFirst );
CGColorSpaceRelease(clrRf);
CGContextDrawImage(ctx, CGRectMake(0, 0, scale.width, scale.height), inImageRef);
CGImageRef img = CGBitmapContextCreateImage(ctx);
UIImage *image = [[UIImage alloc] initWithCGImage:img scale:1 orientation:UIImageOrientationUp];
CGImageRelease(img);
CGContextRelease(ctx);
return image;
}
}
- (UIImage *)tileForRow: (int)row column: (int)col size: (CGSize)tileSize image: (UIImage*)inImage
{
@autoreleasepool {
//get the selected tile
CGRect subRect = CGRectMake(col*tileSize.width, row * tileSize.height, tileSize.width, tileSize.height);
CGImageRef inImageRef = [inImage CGImage];
CGImageRef tiledImage = CGImageCreateWithImageInRect(inImageRef, subRect);
UIImage *tileImage = [[UIImage alloc] initWithCGImage:tiledImage scale:1 orientation:UIImageOrientationUp];
CGImageRelease(tiledImage);
return tileImage;
}
}
现在我从来没有在内存管理方面做得那么好,所以我确实花时间阅读它,并将我的项目转换为 ARC,看看是否可以解决我的问题(那是前一段时间),但从结果来看,我在仪器中对其进行分析后,我必须做一些非常错误的事情,以使内存泄漏得如此糟糕,但我只是看不出我做错了什么。
如果有人能指出我可能做错的任何事情,那就太好了!
谢谢
利亚姆
(如果您需要更多信息,请告诉我)