在ARC下,卸载视图控制器时是否需要将所有强成员设置为零?这是必须的吗



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

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

viewDidLoad功能中,我设置了

a = [[NSSString alloc] init];

在另一个控制器B中,

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

控制器A的成员会被释放吗?

是的,当controllerA被释放时,a指向的字符串将被释放。您不需要自己将其设置为nil

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

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

在iOS 5中,当使用ARC和启用僵尸时,有一个众所周知的错误可以阻止ivar的发布:技术问答;一个QA1758。

否则,ivar将自动释放。

更新2:

今天早上,我花了几个小时诊断和记录了将在iOS 5项目中发布的ivar的失败,之后我发现,如果僵尸在iOS 5上打开并运行,则ARC项目中不会发布实例变量。即将用这些非凡的发现更新我的答案时,Calin非常独立地向我指出,这是众所周知的行为。技术问答;一个QA1758。谢谢Calin!

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

更新:

我之前曾声称这是不正确的,除非将变量和属性设置为nil,否则它们不会被释放。我提供了以下代码作为示例。这是从一个真实的ARC测试项目中获得的,我甚至用另一个视图控制器重新创建了它,除了下面的代码之外,它什么都没有。在一片理所当然的反对声之后,我把这个代码样本放在了一个新项目中,ivar被释放了,这是应该的

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

无论如何,需要明确的是,您的ivar是在父对象被释放时被释放的。我不知道为什么在下面的案例中我没有发布,但这对最初的问题来说无关紧要。

//  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

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

2012-07-12 10:33:33.644测试4〔36045:11903〕-〔ArcSimpleTestViewController解除锁定〕

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

2012-07-12 10:35:23.117测试4〔36083:11903〕-〔ArcSimpleTestViewController解除锁定〕

2012-07-12 10:35:23.119测试4〔36083:11903〕-〔IvarObject2解除锁定〕

对于我上面的撤回,当我把同样的代码放在一个新项目中时,无论我是否为零,我都会看到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");
}

最新更新