内存没有被正确释放?

时间:2010-11-27 07:52:31

标签: iphone objective-c memory nsdictionary nsdata

我的应用程序按特定顺序从URL下载图像,用户可以查看它们。我让应用程序预加载下一个图像并将旧图像保存在缓存中。

此缓存基本上是一个NSMutableDictionary,其中的键与图像ID相关联。缓存中的每个对象也是带有url,图像URL,标题和NSData对象的NSDictionary。当我下载图像时,我使用这些元素将新的字典对象添加到缓存中。我存储NSData对象,如下所示:NSData * imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageurl]];然后我将这个对象添加到子字典对象。

在存储和缓存大量照片后,这显然占用了大量RAM,因此我通过清除整个缓存来响应内存警告。问题是,无论我尝试过什么,都不会释放RAM。对象消失(就像他们应该的那样),但是不要回放RAM。我尝试过以下操作:

  • 循环缓存字典,释放子字典中的数据对象,然后当所有项目循环播放时,删除所有缓存字典子对象。
  • 循环缓存字典,释放子字典,完成后删除所有对象
  • 甚至删除所有对象,然后释放整个缓存对象(然后重新创建它,因为它仍然需要使用)
  • 其他随机组合释放,移除等

问题是,我没试过释放过RAM。释放NSData对象的内存有什么问题吗?

2 个答案:

答案 0 :(得分:1)

内存管理在Objective-C中的工作方式是通过alloc / initing,-retaining或-copying来获取对象的所有权,并在不再需要时通过-release或-autorelease来解除它。

您想要做的是:

1)创建数据对象

NSData *imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageurl]]; 

您现在拥有imgData指向的对象。

2)将该对象添加到您的子词典

[childDictionary setObject:imgData forKey:@"imgData"];

3)关闭数据对象。你不再需要它了。 childDictionary需要它,但这不是你的问题。与所有其他对象一样,childDictionary负责管理自己的内存和所有权。

[imgData release];

您可以这样做的另一种方法是创建数据对象的自动释放版本,并将其添加到数据对象中。

接下来,您需要确保正确管理childDictionary的内存以及cache的内存。例如:

1)创建一个自动释放的childDictionary

NSMutableDictionary *childDictionary = [NSMutableDictionary dictionary];

2)将内容添加到childDictionary(就像我们之前做的那样)

3)将childDictionary添加到缓存

[cache setObject:childDictionary forKey:yourKey];

4)由于childDictionary是自动释放的,因此您现在不需要(也不应该)释放它,因为您不需要它。它将在以后由主自动释放池自动释放。如果您使用以下方法创建了childDictionary:

NSMutableDictionary *childDictionary = [[NSMutableDictionary alloc] init];

返回retainCount为1的对象,那么您现在需要解除所有权:

[childDictionary release];

就缓存而言,您可能希望将其保留很长时间:它很可能是任何对象管理缓存的实例变量,当您点击内存警告时它会被[cache removeAllObjects]重置

如果你使用垃圾收集在Mac上进行开发,那么所有这些都是无用的。但是,既然您正在通话,您需要了解有关内存管理的这些简单规则。我的解释真的忽略了你应该熟悉的很多概念,所以我强烈建议你阅读the Apple documentation about this

答案 1 :(得分:0)

演示此泄漏的简化代码示例会很有帮助。仅从您的描述中,您用于将imgData添加到字典中的调用是否可能会保留它?如果你没有立即在自己的代码中释放imgData,那么你的保留计数为2.当你的本地imgData指针超出范围时,你就会泄漏内存。不过,这只是在没有代码示例的黑暗中刺伤。