在ARC下,卸载viewcontroller时需要为所有强成员设置nil吗?这是必须的吗?

时间:2012-07-12 04:23:59

标签: ios memory automatic-ref-counting

假设我有一个这样的视图控制器:

@interface ControllerA : viewcontroller{
    NSString * __strong a;
}

@end

并在viewDidLoad函数中设置

a = [[NSSString alloc] init];

在另一个ControllerB中,

{
    ControllerA * controllerA = [[ControllerA alloc] init];
}

controllerA的成员会被释放吗?

4 个答案:

答案 0 :(得分:5)

是的,a指向的字符串将在controllerA解除分配时释放。您无需自己将其设置为nil

Transitioning to ARC Release Notes目前是查找有关使用ARC的更多信息的地方。它的一个重点是,如果您的类需要执行任何操作而不是在实例被释放时释放实例变量,您可能仍需要自定义-dealloc

答案 1 :(得分:4)

除非您希望尽快确保其释放(即非ARC代码下的[myObject release]),否则您永远不需要在ARC中将变量设置为nil。取消分配对象后,将自动释放所有iVars。

答案 2 :(得分:2)

在使用ARC和Zombies时,iOS 5中存在一个众所周知的错误,可以防止ivars被释放:Technical Q&A QA1758

否则,ivars将自动释放。

答案 3 :(得分:1)

更新2:

我花了几个小时诊断并记录今天早上在我的iOS 5项目中发布的ivars失败的几个小时后,我发现如果僵尸打开并在iOS 5上运行,则ARC项目中不会发布实例变量关于用这些非凡的发现更新我的答案,相当独立,Calin向我指出这是众所周知的行为。 Technical Q&A QA1758。谢谢Calin!

我的示例项目位于https://github.com/robertmryan/arc-problem-project

<强>更新

我之前声称这是不正确的,除非您将它们设置为nil,否则不会取消分配变量和属性。我提供了以下代码作为示例。这是从一个真正的ARC测试项目中获取的,我甚至用另一个视图控制器重新创建它,除了下面的代码确认之外绝对没有。在得到了当之无愧的反对意见之后,我将这个代码示例放在一个新项目中,并将ivar解除分配,应该是这样。

所以它必须是有问题的项目。我已经完全取消了该项目的所有内容,除了下面的代码(以及执行推送segue的视图控制器,以便我可以弹回它来演示解除分配),问题仍然存在。如果我将代码(和故事板)复制到一个新项目,它可以正常工作。非常,非常奇怪,我会更深入地了解这一点。如果你想看我的项目,那就是https://github.com/robertmryan/arc-problem-project。也许其他人可以看到问题所在。我知道我可以放弃这个项目(它甚至不是一个生产应用程序,只是一个测试平台),但令人担心的是ARC的dealloc可能只是神奇地无法正常工作。

无论如何,要清楚,当父对象被释放时,你的ivars 释放。我不知道为什么我在下面的案例中没有发布,但这对原来的问题并不重要。

//  ArcTestViewController.m

#import "ArcTestViewController.h"

#pragma mark - IvarObject

@interface IvarObject : NSObject
@end

@implementation IvarObject

- (void)dealloc
{
    NSLog(@"%s", __FUNCTION__);
}

@end

#pragma mark - ArcTestViewController

@interface ArcTestViewController ()
{
    IvarObject __strong *_ivarObject;
}
@end


@implementation ArcTestViewController

- (void)dealloc
{
    NSLog(@"%s", __FUNCTION__);

//    _ivarObject = nil;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    _ivarObject = [[IvarObject alloc] init];
}

@end

当我使用注释掉的=nil方法中的dealloc语句执行此操作时,我在控制台上看到以下内容:

  

2012-07-12 10:33:33.644 test4 [36045:11903] - [ArcSimpleTestViewController dealloc]

当我在=nil中取消注释dealloc语句时,我会看到以下内容:

  

2012-07-12 10:35:23.117 test4 [36083:11903] - [ArcSimpleTestViewController dealloc]

     

2012-07-12 10:35:23.119 test4 [36083:11903] - [IvarObject2 dealloc]

对于我的撤回,当我将相同的代码放在一个新项目中时,我会看到deallocs是否为零。

Rob Napier在下面提供了代码示例(我很感激他和其他人花时间),但是当我把它放在另一个项目中时,即使上面的代码也能正常工作,但在我当前的项目中,它并没有正确释放!


Rob Napier的更新:更简单的示例(所有在一个文件中),演示了它的工作原理。把它放在一个文件中并按照指示进行编译:

//  arc.m
//  Compile with:
//      clang -fobjc-arc -framework Foundation -o arc arc.m

#import <Foundation/Foundation.h>

#pragma mark - IvarObject

@interface IvarObject : NSObject
@end

@implementation IvarObject

- (void)dealloc
{
    NSLog(@"%s", __FUNCTION__);
}

@end

#pragma mark - PropertyObject

@interface PropertyObject : NSObject
@end

@implementation PropertyObject

- (void)dealloc
{
    NSLog(@"%s", __FUNCTION__);
}

@end


#pragma mark - ArcTest

@interface ArcTest : NSObject
{
    IvarObject __strong *_ivarObject;
}

@property (nonatomic, strong) PropertyObject *propertyObject;

@end


@implementation ArcTest

@synthesize propertyObject = _propertyObject;

- (void)dealloc
{
    NSLog(@"%s", __FUNCTION__);

//    _ivarObject = nil;
//    _propertyObject = nil;
}

- (void)assignStuff
{
    _ivarObject = [[IvarObject alloc] init];
    self.propertyObject = [[PropertyObject alloc] init];
}

@end

int main () {
    ArcTest *test = [[ArcTest alloc] init];
    [test assignStuff];
    test = nil;
    NSLog(@"End program");
}