好吧,如果我写了很多代码而没有分配任何对象,那么内存在哪里?
例如,而不是
UIImage *myImage = [UIImage imageNamed:@"image.png"];
imageView.image = myImage;
[myImage release];
我有
imageView.image = [UIImage imageNamed:@"image.png"];
贯穿我的所有代码。我没有看到第二个例子中内存发生了什么。我还在学习,并在整个应用程序中使用第二个示例编写了大量代码,而没有分配任何对象。它总是在模拟器中运行良好,但实际设备无法处理内存和崩溃。关于内存管理的所有教程都是在释放你创建的对象的意义上讨论它,但由于我从未创建过任何对象,所以我被卡住了。
答案 0 :(得分:4)
UIImage *myImage = [UIImage imageNamed:@"image.png"];
imageView.image = myImage;
[myImage release];
你做了双重发布。 [UIImage imageNamed]是自动释放的,因此您无需显式释放该对象。您的应用程序可能因双重释放而崩溃,而不是因为未发布的对象。
阅读简单的经验法则release/autorelease confusion in cocoa for iphone:
规则很简单:如果你分配,复制或保留,那就是你的 责任释放。如果你没有,那就不是。但是,如果你 需要依靠留在周围的物体,你必须保留(和 随后发布)。
更多例子:
imageView.image = [UIImage imageNamed:@"image.png"];
以上代码有效,您无需发布。但是如果你使用未发布的对象(例如这个)进行很多直接赋值:
foo.bar = [[SomeClass alloc] initWithSomething:@"Init"];
您可以通过添加自动释放来轻松修复它们:
foo.bar = [[SomeClass alloc] initWithSomething:@"Init"] autorelease];
或者如果你想要长但可以说是更合适的方式(因为你控制了对象的释放时间):
SomeClass *tempVar = [[SomeClass alloc] initWithSomething:@"Init"];
foo.bar = tempVar;
[tempVar release];
答案 1 :(得分:2)
imageView.image = [UIImage imageNamed:@"image.png"];
这条线很棒且正确。
在imageNamed:
方法的实现中,它可以为新的UIImage
分配内存,将新的UIImage
实例化到该内存中,然后在返回之前autorelease
它。代码运行后,自动释放池会耗尽,如果没有任何内容保留,则取消分配图像对象。
那么“记忆在哪里?”。它将进入自动释放池。但实际上,除非您致电alloc
或copy...
或retain
,否则您无需关心。
正如Manny所说,你的第一个代码片段过度释放并且不正确。
答案 2 :(得分:1)
您在使用分配内存/对象来声明变量时感到困惑。在上述两种情况下,代码的重要部分实际上是:
[UIImage imageNamed:@"image.png"];
此代码恰好在UIImage类上调用类方法,该方法执行许多操作。其中一个是UIImage对象的分配和初始化。在第一个示例中,您将此分配的对象存储到名为myImage
的变量中。然后,您将闪亮的新对象移动到另一个(类)变量`imageView.image'。
UIImage *myImage = ...
在第二个示例中,您给出的仍然是将此分配的对象存储在变量中,除了在这种情况下您跳过了中间分配并将对象直接存储到类变量imageView.image
中。
imageView.image = [UIImage imageNamed:@"image.png"];
考虑变量与对象的一种方法是将它们与房屋进行比较。在这种情况下,变量是您的地址,对象就是您的房子。有几个人可以得到你的地址,但无论他们有多少人,当他们选择访问时,他们都会去同一所房子。因此,在您的示例中,myImage
和imageView.image
是指向同一房屋或对象的地址,即UIImage的实例。在您的示例中,您实际上不需要创建中间变量,除非您将其用于其他目的。
就崩溃而言,你应该阅读Apple's memory management guide。这可能需要一段时间,但您将习惯Apple在保留和释放对象方面遵循的标准。请注意XCode 4.2中的新自动引用计数
缓解了很多这些问题,但它也有自己的学习曲线。但总而言之,您正在崩溃,因为您正在发布一个您不拥有的对象。 UIImage上的类方法imageNamed
返回该类的自动释放实例。您无需在代码中向其发送另一个版本,这可能是程序崩溃的原因。