【问题标题】:Release in viewDidUnload and dealloc both?在 viewDidUnload 和 dealloc 中释放?
【发布时间】:2011-01-22 03:19:05
【问题描述】:

我一直假设在释放控制器时总是调用viewDidUnload。这是一个正确的假设吗?

我刚刚探索了一些奇怪的东西,并在我的控制器的viewDidUnload 中设置了一个断点,它是dealloc。似乎调用了dealloc,但从未调用过viewDidUnload 方法。我什至在我的dealloc 中添加了一个self.view = nil,但它似乎仍然没有调用它。

这是否意味着我在viewDidUnload 方法中释放的保留视图对象也需要在我的dealloc 方法中释放以确保它们真的消失?

我知道 StackOverflow 上还有很多其他关于 viewDidUnload 的问题,但没有一个专门针对这两种方法之间发布声明重复的问题。


在 3.1.2 SDK 的新项目中更具体的示例:

@implementation TestViewController

@synthesize label;

- (IBAction)push {
    TestViewController *controller = [[[TestViewController alloc] initWithNibName:@"TestViewController" bundle:nil] autorelease];
    [self.navigationController pushViewController:controller animated:YES];
}

- (void)viewDidUnload {
    self.label = nil;
    NSLog(@"viewDidUnload was called");
}

- (void)dealloc {
    [super dealloc];
    NSLog(@"label retain count: %i", [label retainCount]);
}

@end

我的应用程序委托创建了一个简单的导航控制器,其中一个作为它的根控制器。当我点击链接到push的按钮3次,然后点击返回按钮3次时,会生成以下输出。

ViewDidUnloadTest[2887:207] label retain count: 2
ViewDidUnloadTest[2887:207] label retain count: 2
ViewDidUnloadTest[2887:207] label retain count: 2

这比我认为的要高 2 倍。由视图保留一次,由控制器保留一次。但在dealloc 之后,我预计视图会消失并释放我的标签,控制器会调用viewDidUnload 并释放它。虽然此时可能有一个autorelease 在里面抛出计数。

但至少很明显 viewDidUnload 根本没有被调用,这与这里的答案相反:Are viewDidUnload and dealloc always called when tearing down a UIViewController?

也许我应该在控制器上的所有 dealloc 方法中简单地调用 [self viewDidUnload]?比可能发生的更糟糕的是,我将一个属性设置为 nil 两次,对吧?

【问题讨论】:

    标签: objective-c memory-management uiviewcontroller


    【解决方案1】:

    除非您需要中断保留循环,否则您应该一般只在您的dealloc 方法中释放对象。 viewDidUnload 是个例外;它在内存不足的情况下被调用,应该用于释放任何你可以释放的东西。

    如果您确实需要在其他任何地方释放它们,请始终在 release 之后将引用设置为 nil。这将保护您的应用不会在以后崩溃(可能在 dealloc 中)。

    请注意,文档非常明确地指出,当调用 viewDidUnload 时,视图属性已经为零。

    【讨论】:

    • 完全正确; viewDidUnload 用于内存不足的情况,而 dealloc 用于清理。两者是正交的。
    • 这是一个非常令人困惑的例子!大多数示例显示在 viewDidUnload 中将事物设置为 nil。它无法解释的是,在将某些内容设置为 nil 后,您无法释放它并期望它释放!如果不注意这一点,您最终会到处出现内存泄漏。感谢您的有用帖子。
    • @jocull 将保留属性设置为 nil 实际上会释放它,只要您在其他地方没有另一个保留引用,它就会解除分配。
    • 这就是保留属性的全部意义——当您调用setFoo: 时,旧的foo 值会被释放,而新的值会被保留。在此处阅读 retain 属性属性:developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/…
    • 是的——没有bar = nil;[bar release];很高兴创建一个悬空指针!
    猜你喜欢
    • 2011-04-05
    • 2011-03-14
    • 2012-05-04
    • 2011-07-01
    • 2011-11-09
    • 2012-04-10
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多