分配给强 属性 的内存是否会在 属性 设置为 nil 后立即释放?

Is the memory assigned to a strong property released as soon as the property is set to nil?

我想知道如何释放强property/iVar。我想澄清为什么我打算这样做。我通过以下任一声明拥有一个对象:

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

@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。但是内存占用还是会上升,只有在程序结束时才会下降。

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


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

解决方案:

我通过将所有 strong property/iVar 放在 @autoreleasepool 中解决了这个问题(如已接受的答案中所建议的那样),以便它们在当前 运行 循环。调试很有帮助(正如 Sulthan 所说)。

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

经验教训:

分配 nil 将立即发送释放消息。但是,"some function call which returns a MyObject object" 可能会 return 一个自动释放的对象,它会从自动释放池中保留一个计数,直到池消失。您可以通过创建自己的自动释放池来解决这个问题。

""Is the memory assigned to a strong property released as soon as the property is set to nil ?""

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

The Application Kit creates an autorelease pool on the main thread at the beginning of every cycle of the event loop, and drains it at the end, thereby releasing any autoreleased objects generated while processing an event.

分配 nil 时,您只能确定一件事。该对象将收到 releaseautorelease 消息。 ARC 不保证是哪一个。

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

当某些内存没有释放时,通常意味着有另一个强引用持有对象或者对象本身没有正确释放内存。

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

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

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

nil 分配给强变量确实表明您不再需要该变量引用的对象,并且假设不存在对该对象的其他强引用 ARC将快速处理该对象,如果不是立即的话。

您的对象可能(见末)被自动释放池引用,这本质上是一个历史遗留物ARC 天,这会阻止您预期的内存释放——因为仍然有一个强引用。

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

通常 "not too distant future" 是事件循环的下一次迭代,但您可以引入本地范围,当退出时,将放弃在该范围内添加到池中的所有对象的所有权。为此,您可以将代码更改为:

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

如上所述,您的对象只有可能在自动释放池中,如果上述方法不能解决您的问题,那么您还有另一个对潜伏对象的强引用某处...

HTH