-1

我正在尝试制作某种谜题,但在 5-10 次随机播放后我收到内存警告,现在我正在尝试添加谜题并将其从超级视图中删除,但是,仍然存在某种内存韭菜..有人可以帮我吗?

- (void)setup6x6
{
    int num = 0;
    for (int i = 0; i < 6; i++)
    {
        for (int j = 0; j < 6; j++)
        {
            UIImageView * imgView = [[UIImageView alloc] init];

            cor = arc4random()%4;
            nCor = arc4random()%8;
            maxCor = arc4random()%16;

            scale = _pImage.size.width / puzzleArea.frame.size.width;
            NSString * imageName1;
            UIImage * imageToMask1;
            UIImage * maskedImage1;
            if (i == 0)
            {
                if (j == 0)
                {
                    imageName1 = [topLeftCornerPuzzles objectAtIndex:cor];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake(0,
                                                                              58 * i * scale,
                                                                              58 * scale,
                                                                              58 * scale)];
                }
                else if (j == 5)
                {
                    imageName1 = [self checkPreviousInArray6x6:puzzles new:[topRightCornerPuzzles objectAtIndex:cor] index:num];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake((42 + 50*(j-1)) * scale,
                                                                              58 * i * scale,
                                                                              58 * scale,
                                                                              58 * scale)];
                }
                else
                {
                    imageName1 = [self checkPreviousInArray6x6:puzzles new:[topPuzzles objectAtIndex:nCor] index:num];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake((42 + 50*(j-1)) * scale,
                                                                              58 * i * scale,
                                                                              66 * scale,
                                                                              58* scale)];
                }
            }
            else if (i < 5)
            {
                if (j == 0)
                {
                    imageName1 = [self checkPreviousInArray6x6:puzzles new:[leftPuzzles objectAtIndex:nCor] index:num];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake(0,
                                                                              (42 + 50*(i-1)) * scale,
                                                                              58 * scale,
                                                                              66 * scale)];
                }
                else if (j == 5)
                {
                    imageName1 = [self checkPreviousInArray6x6:puzzles new:[rightPuzzles objectAtIndex:nCor] index:num];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake((42 + 50*(j-1)) * scale,
                                                                              (42 + 50*(i-1)) * scale,
                                                                              58 * scale,
                                                                              66 * scale)];
                }
                else
                {
                    imageName1 = [self checkPreviousInArray6x6:puzzles new:[middlePuzzles objectAtIndex:maxCor] index:num];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake((42 + 50*(j-1)) * scale,
                                                                              (42 + 50*(i-1)) * scale,
                                                                              66 * scale,
                                                                              66 * scale)];
                }
            }
            else
            {
                if (j == 0)
                {
                    imageName1 = [self checkPreviousInArray6x6:puzzles new:[bottomLeftCornerPuzzles objectAtIndex:cor] index:num];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake(0,
                                                                              (42 + 50*(i-1)) * scale,
                                                                              58 * scale,
                                                                              58 * scale)];
                }
                else if (j == 5)
                {
                    imageName1 = [self checkPreviousInArray6x6:puzzles new:[bottomRightCornerPuzzles objectAtIndex:cor] index:num];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake((42 + 50*(j-1)) * scale,
                                                                              (42 + 50*(i-1)) * scale,
                                                                              58 * scale,
                                                                              58 * scale)];
                }
                else
                {
                    imageName1 = [self checkPreviousInArray6x6:puzzles new:[bottomPuzzles objectAtIndex:nCor] index:num];
                    imageToMask1 = [self cropImage:_pImage withRect:CGRectMake((42 + 50*(j-1)) * scale,
                                                                              (42 + 50*(i-1)) * scale,
                                                                              66 * scale,
                                                                              58 * scale)];
                }
            }
            [puzzles addObject:imageName1];
            maskedImage1 = [self maskImage:imageToMask1 withMask:[UIImage imageNamed:imageName1]];
            [imgView setImage:maskedImage1];

            if (i == 0)
                originY = 0;
            else
                originY = 50 * (i-1) + 42;

            if (j == 0)
                originX = 0;
            else
                originX = 50 * (j-1) + 42;

            if (j == 0 || j == 5)
                sizeW = 58;
            else
                sizeW = 66;

            if (i == 0 || i == 5)
                sizeH = 58;
            else
                sizeH = 66;

            [imgView setFrame:CGRectMake(originX, originY, sizeW, sizeH)];
            [puzzleArea addSubview:imgView];
            [imgView removeFromSuperview];
            //[maskedImage1 release];
            imageToMask1 = nil;
            maskedImage1 = nil;
            [imgView release];
            [imageName1 release];
            //[imageToMask1 release];
            num += 1;
        }
    }
}

我是如何裁剪的:

- (UIImage *)cropImage:(UIImage *)image withRect:(CGRect)cropRect
{
    return [UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage, cropRect)];
}

还有我如何掩盖:

- (UIImage *)maskImage:(UIImage *)image withMask:(UIImage *)maskImg
{
    CGImageRef maskRef = maskImg.CGImage;
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                        CGImageGetHeight(maskRef),
                                        CGImageGetBitsPerComponent(maskRef),
                                        CGImageGetBitsPerPixel(maskRef),
                                        CGImageGetBytesPerRow(maskRef),
                                        CGImageGetDataProvider(maskRef),
                                        NULL,
                                        false);
    return [UIImage imageWithCGImage:CGImageCreateWithMask([image CGImage], mask)];
    CGImageRelease(maskRef);
    CGImageRelease(mask);
}

我不明白如果我释放所有内容,为什么会收到内存警告。但是,如果我尝试释放 maskedImage1 或 imageToMask1 我也会收到错误...

4

2 回答 2

1

每次创建 时CGImage,都需要释放它。UIImage不会为你这样做。

CGImage如果您没有创建它,则不应发布它。在您的第二种方法中,您不应该这样CGImageRelease(maskRef)

当您return从一个方法开始时,该语句之后的代码不会被执行。

- (UIImage *)cropImage:(UIImage *)image withRect:(CGRect)cropRect
{
    CGImageRef croppedCGImage = CGImageCreateWithImageInRect(image.CGImage, cropRect);
    UIImage *croppedUIImage = [UIImage imageWithCGImage:croppedCGImage];
    CGImageRelease(croppedCGImage);
    return croppedUIImage;
}

- (UIImage *)maskImage:(UIImage *)image withMask:(UIImage *)maskImg
{
    CGImageRef maskRef = maskImg.CGImage;
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                        CGImageGetHeight(maskRef),
                                        CGImageGetBitsPerComponent(maskRef),
                                        CGImageGetBitsPerPixel(maskRef),
                                        CGImageGetBytesPerRow(maskRef),
                                        CGImageGetDataProvider(maskRef),
                                        NULL,
                                        false);
    CGImageRef maskedCGImage = CGImageCreateWithMask([image CGImage], mask);
    UIImage *maskedUIImage = [UIImage imageWithCGImage:maskedCGImage];
    CGImageRelease(maskedCGImage);
    CGImageRelease(mask);
    return maskedUIImage;
}
于 2013-07-04T19:03:23.580 回答
1

经验法则是“释放你拥有的一切”

每当您调用以alloccopynew或开头的方法时,您就获得了对象的所有权retain(这些只是约定,但很多 Objective-C 都是如此)。

每当您调用release或时,您都会失去对象的所有权autorelease

如果我们按照这些准则查看您的代码,您会发现您正在释放几个您从未拥有过的对象。

  • 你正确alloc然后release imgView
  • 您发布imageName1时无需分配、复制或保留它。这可能会导致崩溃。(我假设checkPreviousInArray6x6:new:index:不返回它拥有的对象)。

对于MaskImage:withMask:CG 类型遵循类似的规则。

  • maskRef永远不会保留,复制等,因此不应发布。
  • mask正在正确创建和发布。

但是,这种方法有一个大问题:后面的行return永远不会被调用,因此内存永远不会被清理。

我建议在您的代码上运行静态分析器,因为它可以帮助捕获许多错误。

有关手动内存管理的完整细节,我建议阅读Advanced Memory Management Programming Guide

于 2013-07-04T19:04:01.797 回答