一旦属性设置为nil,就会释放分配给强属性的内存吗?

时间:2015-05-25 16:53:11

标签: objective-c memory-management automatic-ref-counting

我想知道如何发布一个强大的属性/ iVar。我想澄清为什么我打算这样做。我通过以下任何一个声明拥有一个对象:

@interface MyClass : NSObject 
     @property (readwrite, nonatomic) MyObject *hugeObject;
@end

OR

@interface MyClass : NSObject {
     MyObject *hugeObject;
}
@end

我用某种方法创建这个对象,我在另一种方法中使用它等等

- (void)someMethod {
     hugeObject = [[MyObject alloc] init];
}

- (void)someOtherMethod {
     hugeObject = //some function call which returns a MyObject object
     //do something with hugeObject
}

现在,someOtherMethod被多次调用,每次hugeObject必须存储一个新值。我不再需要以前的价值,因为它很重,我想摆脱它。所以我用这种方式修改了someOtherMethod

- (void)someOtherMethod {
     hugeObject = //some function call which returns a MyObject object
     //do something with hugeObject
     hugeObject = nil;
}

我不想等到dealloc,所以将它分配给nil。但是内存使用率仍在上升,只有在程序结束时才会减少。

所以,这就是我困惑的地方:

  • 一旦属性设置为nil,是否释放了分配给强属性的内存?
  • 或仅在ARC单独调用dealloc时释放内存?

问题识别:指向对象的强引用。

解决方案:

我通过将所有strong属性/ iVar放在@autoreleasepool中(在接受的答案中为sugessted)来解决它,以便在当前运行循环结束时释放它们。调试有助于魅力(由Sulthan提供)。

注意:确保@autoreleasepool是本地范围的池,否则会阻止您期望的内存释放 - 因为仍然会有强大的引用。

经验教训

  • 分配nil时,您只能确定一件事。该对象将被发送releaseautorelease消息。 ARC不保证哪一个
  • 如果没有更多强引用指向该对象,则内存将立即(release情况)或当前循环结束时释放(autorelease情况)。

4 个答案:

答案 0 :(得分:2)

分配nil时,您可以确定只有一件事。该对象将被发送releaseautorelease消息。 ARC不保证哪一个。

如果没有更多强引用指向该对象,则内存将立即释放(release情况)或在当前循环结束时(autorelease情况) - 这意味着只需几分之一秒。

当某些内存未被释放时,通常这意味着有另一个强引用持有该对象或该对象本身不能正确释放内存。

在你的情况下,你甚至不清楚如何检查对象是否已被释放。最简单的检查是使用dealloc

中的登录
- (void)dealloc {
   NSLog(@"Huge object has been removed from memory");
}

请注意,分配给应用程序的内存量不等于应用程序实际使用的内存量。如果您需要有关内存分配的真实信息,请在Inspector中使用Memory Profiler。

答案 1 :(得分:1)

nil分配给强变量确实表明您不再需要该变量引用的对象,并且未提供对该对象的其他强引用 ARC将处置该对象很快,如果不是立即。

自动释放池引用的对象可能是(请参阅结束),这实际上是ARC前几天留下的历史人工制品,这样可以防止你期望的记忆释放 - 因为仍然有很强的参考。

主要是为了使人类能够应对手动引用计数(MRC),自动释放池接受对象的所有权,直到不久的将来某一点,此时它放弃了所有权。使用自动释放池简化了MRC,但在ARC时代它不是必需但仍然存在 - 主要是因为现有的大量代码依赖于它。

通常"不太遥远的未来"是事件循环的下一个迭代,但您可以引入本地范围,退出时将放弃在该范围内添加到池中的所有对象的所有权。为此,您可以将代码更改为:

- (void)someOtherMethod
{
   @autoreleasepool // make a locally scope pool
   {
      hugeObject = //some function call which returns a MyObject object
      //do something with hugeObject
      hugeObject = nil;
   }
}

如上所述,只有可能您的对象位于自动释放池中,如果上述方法无法解决您的问题,那么您可以对某个潜伏的对象进行另一个强引用... < / p>

HTH

答案 2 :(得分:-1)

分配nil会立即发送一条释放消息。然而,&#34;一些函数调用返回一个MyObject对象&#34;可能会返回一个自动释放的对象,该对象将具有自动释放池的保留计数,直到池消失。您可以通过创建自己的自动释放池来解决这个问题。

答案 3 :(得分:-1)

“”一旦属性设置为nil,是否释放了分配给强属性的内存?“”

可能。它应该在NSAutoReleasePool中发布。以下是有关自动释放池及其运行频率的一些信息 来自Apple的NSAutoreleasePool文档:

  

Application Kit在主线程上创建一个自动释放池   事件循环的每个循环的开始,并将其排出   结束,从而释放任何生成的自动释放对象   处理事件。