内存泄露
内存泄漏的仪器。这是用来找到第一类泄漏前面提到的 - 当一个对象不再被引用时出现的那种。
检测泄漏是可以理解的一个很复杂的事情,但泄漏的工具记得,已分配的所有对象,并定期通过扫描每个对象以确定是否有任何不能从任何其他对象访问的。
关闭仪器,回到Xcode和选择Product->Profile
回到你的应用程序!执行搜索,得到结果。然后点选结果的预览行打开全屏浏览器。按下旋转按钮在左上角,然后再按一次。
回到仪器,等待片刻。如果你已经正确地完成上述步骤后,你会发现泄漏已经出现了!你的工具窗口将看起来像这样:
返回到模拟器,并按下旋转几次。然后返回到仪器和等会,得到如下结果:
哪来的泄漏从哪里来?扩展详细信息面板
在扩展的详细信息面板打开CGContext上名单。在列表中选择CGContext上的元素之一,这表明导致要创建的对象,如下面的堆栈跟踪:
再次,涉及到你的代码中的帧显示为黑色。由于只有一个,双击它,看看代码的方法。
有问题的方法是rotateTapped: ,这是被调用时被窃听旋转按钮的处理程序。这种方法旋转原始图像,并创建一个新的图像,如下:
- - (void)rotateTapped:(id)sender {
- UIImage *currentImage = _imageView.image;
- CGImageRef currentCGImage = currentImage.CGImage;
- CGSize originalSize = currentImage.size;
- CGSize rotatedSize = CGSizeMake(originalSize.height, originalSize.width);
- CGContextRef context = CGBitmapContextCreate(NULL,
- rotatedSize.width,
- rotatedSize.height,
- CGImageGetBitsPerComponent(currentCGImage),
- CGImageGetBitsPerPixel(currentCGImage) * rotatedSize.width,
- CGImageGetColorSpace(currentCGImage),
- CGImageGetBitmapInfo(currentCGImage));
- CGContextTranslateCTM(context, rotatedSize.width, 0.0f);
- CGContextRotateCTM(context, M_PI_2);
- CGContextDrawImage(context, (CGRect){.origin=CGPointZero, .size=originalSize}, currentCGImage);
- CGImageRef newCGImage = CGBitmapContextCreateImage(context);
- UIImage *newImage = [UIImage imageWithCGImage:newCGImage];
- self.imageView.image = newImage;
- }
再次,仪器只能在这里给你一个提示,问题出在哪里,它不能告诉你确切位置的泄漏。这是唯一能够证明你在创建对象泄露的地方.你可能认为ARC并有不可能是造成代码中内存泄漏…对不对?
回想一下,ARC只涉及Objective-C的对象。它不管理保留和的CoreFoundation对象而不是Objective-C的对象的释放。
啊,现在它开始变得明显的问题是什么?
-CGContextRef和CGImageRef对象永远不会被释放!为了解决这个问题,在rotateTapped方法的末尾添加以下两行代码:
- CGImageRelease(newCGImage);
- CGContextRelease(context);
这两种调用都需要来维护这两个对象的保留计数。这个说明,你还需要了解引用计数 - 即使你在你的项目中使用的ARC!
从在Xcode中,使用cmd工具构建和运行应用程序。
在使用泄漏仪器仪器再看看应用程序,看看是否泄漏的被固定。如果你正确地遵循上述步骤,泄漏应消失!