我的应用程序中有一个奇怪的崩溃,没有任何痕迹。这可能是一个与记忆有关的问题,但信息很少,而且我不知道如何进行或修复它。如果它不是仪器本来就没有任何线索。
我有一个图像数组(在本例中是一个大小为2的数组),我在其中加载图像,创建图像上下文&绘制并将其保存到数组中。每次调用该方法时,图像数组对象都会被新内容替换。在仪器中,我看到在此方法调用期间使用非常大的虚拟内存。显然在每次通话记忆后都没有清除&因此崩溃。该项目是ARC。我将在下面列出代码。这就是我们重新创建此问题所需的全部内容。 (我使用的图像大小约为7MB,因此更容易重新创建崩溃)。我也在使用iPad2设备。
+ (UIImage *)imageCopy:(UIImage *)src
{
UIGraphicsBeginImageContext(src.size);
[src drawAtPoint:CGPointZero];
UIImage *r = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return r;
}
- (IBAction)buttonTouch:(id)sender
{
for (int i=0; i<2; i++)
{
if (i==0)
{
self.mImage = [UIImage imageNamed:@"LARGE_elevation.jpg"];
}
else
{
self.mImage = [UIImage imageNamed:@"LARGE_elevation2.jpg"];
}
// imageArray is a NSMutableArray with capacity of 2
[imageArray setObject:[ViewController imageCopy:self.mImage] atIndexedSubscript:i];
}
((UIImageView *)[self.view viewWithTag:100]).image = self.mImage;
}
这是一个来自仪器的屏幕,在发出内存警告后第二次崩溃。
我没有看到我在这里使用的“imageCopy”方法有任何大问题。
对此的任何帮助都非常感谢。 谢谢&amp;欢呼声,
答案 0 :(得分:1)
我发现这是 循环参考 问题。因此,当新内容替换数组中的旧内容时,过去的对象仍然存在。这是一个非常有趣的发现,因为在内存泄漏分析器中,它显示出很少的KB数据泄漏,你不会怀疑,因为非释放的虚拟内存是几百兆字节(MB)。
作为一个非常抽象的例子。
ClassA
@property (strong) ClassB *obj
----------
ClassB
@property (strong) ClassA *obj
- (id)initWithA:(ClassA *)objA;
----------
因此,当您删除A时,任何对象都不会被正确释放。在我的情况下,泄漏分析仪跟踪的泄漏对于两个对象都是几KB,即使CoreGraphics计算挂在虚拟内存中的大约200MB数据上。
修复是将ClassB中的A引用标记为弱。
ClassB
@property (weak) ClassA *obj
- (id)initWithA:(ClassA *)objA;
判决
答案 1 :(得分:0)
问题可能是方法imageNamed:
缓存了加载的图像,并且显然无法以编程方式在内存警告后清除缓存。
您可以使用其他方法(例如imageNamed:
)来缓存图像,而不是initWithData:
。您将找到详细的讨论here。