位图导致设备上的内存泄漏

时间:2016-03-04 13:58:46

标签: ios objective-c memory-leaks bitmap core-graphics

我使用简单的位图技术将文本转换为图像,之后我将此图像划分为栅格,之后我计算每个栅格矩形中黑色像素的百分比。每个东西在模拟器上工作正常但在Device上崩溃了。这是一些相关的代码

-(int)blackValue:(UIImage *)image rect:(CGRect)rect {
    int pixelInRect = (int)rect.size.width * rect.size.height;
    __block int blackCount = 0;
    ImageBitmap * imageBitmap = [[ImageBitmap alloc] initWithImage:image  bitmapInfo:(CGBitmapInfo)kCGImageAlphaNoneSkipLast];
    for (int x = 0; x <(int) rect.size.width; x++) {
        for (int y = 0; y < (int) rect.size.height; y++) {
            Byte * pixel = [imageBitmap pixelAtX:(int)rect.origin.x Y:(int)rect.origin.y];
            Byte red = pixel[0];
            if (red <  0.1)
            {
                blackCount++;
            }
        }
    }
    return blackCount/pixelInRect;
}

- (NSDictionary *)rasterizeBitmap:(UIImage *)image size:(CGFloat)size {
    CGFloat width =(int) (image.size.width/size);
    CGFloat height =(int) (image.size.height/size);
    NSMutableArray *fields = [NSMutableArray array];
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            CGRect rect = CGRectMake(x * size, y * size, size, size);
            CGPoint center = CGPointMake(x * size + size/2.0, image.size.height - (y * size + size/2.0));
            double black = [self blackValue:image rect:rect];
            Field * field = [[Field alloc] init];
            field.center = center;
            field.black = black;
            [fields addObject:field];
        }
    }
    return @{@"width":@(width) , @"fields":fields};
}

当我尝试在Profile中运行它时,得到了以下结果

enter image description here

有人可以建议我如何解决内存问题?

1 个答案:

答案 0 :(得分:3)

问题是你在ImageBitmap对象中手动分配内存,但是你永远不会释放它。

两个嫌疑人是位图上下文(context)和位图数据(contextData)。这两个都不是由ARC管理的,所以一旦你完成它们,你就会想要自己解放这两个。

在ARC中,您只需在dealloc类中实现ImageBitmap方法,并将清理代码放在那里。

例如:

-(void) dealloc {
    CGContextRelease(context); // releases the bitmap context, if it was created (CGContextRelease checks for NULL)
    free(contextData); // releases the bitmap data (it was explicitly created, so no need to check)
}

还值得注意的是,您应该init不可用,并标记您指定的初始值。

这是因为无法使用您的imageFromContextpixelAtX:Y:实例方法,而无需通过自定义initWithSize:bitmapInfo:初始化程序创建实例,因为它会创建位图上下文并为位图数据分配内存。

因此,如果您要通过调用init来创建实例,并调用其中一个实例方法,则很可能会崩溃。

要解决此问题,您可以在init文件中将ImageBitmap.h方法标记为不可用,并将initWithSize:bitmapInfo:方法标记为指定的初始值。

-(instancetype) init NS_UNAVAILABLE;

-(id)initWithSize:(CGSize)size bitmapInfo:(CGBitmapInfo)bmInfo NS_DESIGNATED_INITIALIZER;

所有NS_UNAVAILABLE所做的就是阻止您通过调用init来创建实例,从而强制您使用自定义初始化工具。

如果您尝试执行[[ImageBitmap alloc] init],编译器将显示以下错误:

enter image description here

NS_DESIGNATED_INITIALIZER所做的只是确保ImageBitmap中的任何额外初始化工具必须通过初始化工具创建新实例,并且如果他们不知道,则会显示以下警告:

enter image description here

See here for more info on NS_DESIGNATED_INITIALIZER.

现在,实际上这些只是手续,因为您是唯一一个将要使用此功能的人,并且您知道必须使用自定义初始化程序。但是,如果您想与其他人分享您的代码,那么获得这些手续是正确的。