ARC 内存管理:@Property (nonatomic, strong) VS 实例变量

Posted

技术标签:

【中文标题】ARC 内存管理:@Property (nonatomic, strong) VS 实例变量【英文标题】:ARC Memory management : @Property (nonatomic, strong) VS instance variable 【发布时间】:2013-09-07 11:11:58 【问题描述】:

我在 Xcode 中使用分析工具(分配)发现的是,当您取消一个属性时,它不会被释放,直到父类被取消。现在假设您要确保不在内存中保留昂贵的模态视图控制器(假设它不会经常使用),如果昂贵的 VC 是一个属性,则为该属性分配的内存不会当属性被取消时释放,这意味着当用户想要再次使用昂贵的 VC 时,我们每次将分配相同数量的内存。这在分析器中很容易发现,因为图表一直在攀升。

但是,如果我只将昂贵的 VC 定义为实例变量并定义我自己的 setter&getter,则分析器分配图实际上会在变量被清除时立即减少,并在每次新分配时以相同的数量回升。

所以我的问题是,为什么一个变量“似乎”在定义为实例变量时被释放,但在定义为属性时却没有?

// What I call defining something as an instance variable:
@interface SomeViewController ()

    UIPopoverController *somePopover;


// What I call defining something as a property
@property (nonatomic,strong) UIPopoverController *somePopover;

// Nilling out a property which does not get allocated unless it does not have a parent (root node memory graph wise)
self.somePopover = nil;

// Nilling out an instance variable which does make the memory graph in the profiler go down by the same amount it went up
somePopover = nil;

AFAIK,你不能强制一个对象释放它的所有内存,直到它的父调用 deallocate 并且它的所有子级都被级联释放.. https://***.com/a/7631831/2536815

【问题讨论】:

对于(强)属性“vc”(使用 ARC 和默认设置器),_vc = nilself.vc = nil 之间应该没有区别。两者都将保留计数减一,如果没有其他引用,则对象被释放。 arc 有时会在自动释放池中添加一些东西,但在池耗尽之前它们不会被释放 【参考方案1】:

我不认为你的分析是正确的。如果使用得当,属性和实例变量对引用计数的影响相同:将其设置为 nil 会减少引用计数器,如果它变为 0,则实例(无论是视图控制器还是其他东西)立即释放。

如果在您的应用中不是这种情况,那么原因肯定不是属性与实例变量。

为了进一步分析您的具体问题,我们需要更多信息。因此,请发布您的代码,描述用于测量内存管理效果的设置、有效结果是什么以及您的期望。

【讨论】:

【参考方案2】:

所以看起来我只是将隐藏/显示昂贵的视图与分配/取消混淆了,当视图不可见时内存图会下降,反之亦然,我知道我真的很傻..

只是为了验证您不能强制 arc 释放属性/ivar,我创建了一个新的 xcode 项目,我只是将下面的代码放在 didFinishLaunching 方法中。不幸的是,无论我是否将它们归零,分配给属性和 ivar 的内存都保留在内存中。在我的例子中,下面的代码会生成 2.8 MB 的内存,当此方法完成并且应用程序启动分析器时,内存图会无限期地保持在 2.8 MB。

@interface SSAppDelegate ()

    NSMutableArray *ivVC;

@property (nonatomic, strong) NSMutableArray *propertyVC;
@end
@implementation SSAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions




for (int k=0; k<10; k++) 
    ivVC = [NSMutableArray array]; // Doesn't matter if it's alloc] init]
    self.propertyVC = [NSMutableArray array]; 

    for (int i=0; i<1000;i++) 
        [ivVC addObject:@"..................................................................................."];
        [_propertyVC addObject:@"..................................................................................."];

    

    ivVC = nil;
    self.propertyVC = nil;


self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;

【讨论】:

将 = nil 包装在 @autoreleasepool 中 arc 有时会在池中添加东西,但在池耗尽之前它们不会被释放

以上是关于ARC 内存管理:@Property (nonatomic, strong) VS 实例变量的主要内容,如果未能解决你的问题,请参考以下文章

非ARC开发的内存管理

内存管理总结

@property? @property?说说他身后的事情。

Swift 内存管理与循环引用问题(weakunowned)

关于@property后面修饰符详解

iOS内存管理-ARC