在viewDidUnload中设置为nil,但在dealloc中释放

JoJ*_*oJo 10 iphone cocoa-touch memory-management objective-c

我整天都在阅读有关为什么在viewDidUnload中将视图设置为nil并在dealloc中发布的原因.所有文章都在重复同样的事情.是的,我知道幕后指示是不同的,但实际的区别是什么?

var = nil

  1. 如果var是保留的属性,则回收旧对象var指向的内存.
  2. 将var设置为nil.

[var release]

  1. 回收内存var点.
  2. var现在指向什么,相当于零

对我来说,回收内存的两种方式都有相同的最终结果.那么为什么一个在另一个呢?那里的每本书都告诉我设置为nil in viewDidUnload并释放dealloc.有人应该指出如果一个视图被释放viewDidUnload并被填入的话会发生的坏事dealloc.

.H

#import <UIKit/UIKit.h>
@interface DisclosureDetailController : UIViewController {
 UILabel* label;
}
@property (nonatomic, retain) IBOutlet UILabel* label;
@end
Run Code Online (Sandbox Code Playgroud)

.M

#import "DisclosureDetailController.h"
@implementation DisclosureDetailController
@synthesize label;
- (void)viewDidUnload {
 self.label = nil;
 // OR [self.label release];
 [super viewDidUnload];
}
- (void)dealloc {
 [self.label release];
 // OR self.label = nil;
}
Run Code Online (Sandbox Code Playgroud)

Lil*_*ard 25

首先,行

[self.label release];
Run Code Online (Sandbox Code Playgroud)

无论你在哪里打电话都是绝对错误的.你永远不应该调用-release属性访问的结果.这和写作完全一样[[self label] release],我希望你能认识到这是错误的.

您的代码示例应如下所示:

- (void)viewDidUnload {
    self.label = nil;
    [super viewDidUnload];
}
- (void)dealloc {
    [label release];
    [super dealloc];
}
Run Code Online (Sandbox Code Playgroud)

如果我们先看一下-viewDidUnload,这很简单.self.label = nil;是正确的.同样正确的是[self setLabel:nil];.虽然不太好,但写作也是可以接受的[label release], label = nil;.最后一种形式并不是很好,因为它绕过了setter方法,这可能比简单地释放属性做更多的事情(例如,它可能保持关注属性值的内部状态).它还绕过了KVO通知.

这里真正的问题是你做了什么-dealloc.许多人认为这样说完全没问题self.label = nil;,实际上,这种方法大部分时间都可以使用.问题是,其余的时间会导致细微的错误.调用setter有两件事可以做.首先是它可以在你的类引起的副作用,如果setter方法是手动实现的(即使你不是你自己,一个子类可能实现的setter).第二是它可以播放KVO通知.当你进去的时候,这些都不是你想要的-dealloc.通过直接释放ivar,如同[label release];,您可以避免潜在的副作用和KVO通知.

  • @JoJo:副作用是什么都有.塞特斯只是方法.编译器为你合成了setter,但你可以自己简单地通过编写一个名为(默认情况下)`-setPropertyName:`的方法来实现它们.在此setter中,您可以执行任何操作,包括执行不适合在-dealloc内部执行的操作,例如保留self.同样,KVO通知在-dealloc中是个坏主意.那个应该是显而易见的.你的目标正在消失 - 没有其他人应该对你撕毁你的伊娃所做一个逐个打击的说法. (3认同)
  • @JoJo:是的,指向解除分配对象的指针与1到nil非常不同.前者是指向垃圾内存的指针,如果你试图对它做任何事情(例如在它上面调用`-release`),你几乎肯定会崩溃.另一方面,指向nil的指针是安全的.它会默默地忽略发送给它的任何消息.说'id foo = nil; [foo doSomething];`将完全跳过对`-doSomething`的调用.如果你在`-viewDidUnload`中释放了一个obj,但是没有把它弄清楚,当你试图在`-dealloc`中再次释放它时,或者你使用`self.foo = somethingElse`时,你会崩溃. (3认同)
  • @JoJo:`.`永远不会转换为` - >`.这毫无意义.人们说`[self.property method]`因为一般来说,如果存在属性,属性访问比直接ivar访问更受欢迎.通过坚持访问属性访问,您可以更容易遵守属性强制执行的内存管理语义,如果属性被标记为原因,您将获得原子访问权限,并且您的代码更灵活,因为可以覆盖getter/setter通过子类,甚至自己以后在类的开发中. (2认同)