ARC内存管理:@Property(非原子,强)VS实例变量

时间:2013-09-07 11:11:59

标签: ios objective-c automatic-ref-counting

我在Xcode(分配)中使用分析工具发现的是,当你淘汰一个属性时,在父类被填空之前它不会被释放。现在让我们假设您要确保不在内存中保留昂贵的模态视图控制器(假设它不会经常使用),如果昂贵的VC是属性,则该属性的已分配内存不会当属性被填空时释放,这意味着当用户想再次使用昂贵的VC时,我们每次都会分配相同数量的内存。由于图表不断攀升,因此很容易在剖析器中发现。

然而,如果我只定义了昂贵的VC作为实例变量和定义自己的设定器和放大器;吸气剂分析器分配图实际上降低时立即变量被nilled出来并返回了在每次新的分配相同量的< / p>

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

// 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://stackoverflow.com/a/7631831/2536815

2 个答案:

答案 0 :(得分:6)

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

如果您的应用中不是这种情况,那么原因必须是属性与实例变量之外的其他原因。

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

答案 1 :(得分:0)

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

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

@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;
}