保留属性应始终以dealloc函数释放,这是对的吗?

时间:2013-05-23 07:42:03

标签: ios

我曾经这样做,直到我发现我的一个保留的属性的保留计数在dealloc函数之前为零。 (这种情况是正常还是异常?)

注意:这是一个RC条件,而不是ARC。

例如,我在下面有4个保留属性,它们是否总是以dealloc函数释放?

如果没有,我怎么知道什么时候发布,什么时候不发布?手动判断retainCount?

@property (nonatomic, retain) NSString *fileName;
@property (nonatomic, retain) UIImage *fullSizeImage;
@property (nonatomic, retain) UIImage *thumbnailImage;
@property (nonatomic, retain) UIImageView *checkedImageView;

- (void)dealloc {   

    [checkedImageView release];
    checkedImageView = nil;

    [fileName release];
    fileName = nil;

    [fullSizeImage release];
    fullSizeImage = nil;

    [thumbnailImage release];
    thumbnailImage = nil;

    [super dealloc];
}

5 个答案:

答案 0 :(得分:3)

好吧,如果问题是“总是?”,那么Wain几乎是正确的......

简短的答案是肯定的......

因为一般情况下,当有人设置属性时,这意味着他将使用它作为属性,即他使用其setter方法初始化它。

但是(长答案):不,不要总是:

如果您在代码中的某个位置初始化与该属性关联的私有var而没有它的setter方法,该怎么办?请记住,属性不是var,而只是从Xcode获取方法以获取和设置与之关联的var的有用方法。

换句话说,当你写.h:

@property (nonatomic, retain) NSString *fileName;

和.m:

@synthesize fileName;

您正在声明一个名为fileName的var,并要求xcode为您创建2个(不可见)方法:

一个setter,用于在fileName中设置一个新的保留值:

-(void)setFileName:(NSString *)newString{
    if (fileName == newString) {
        return;
    }
    NSString *oldString = fileName;
    fileName = [newString retain];
    [oldString release];
}

和一个getter,用于获取fileName的值:

-(NSString)fileName{
   return fileName
}

所以,当你在代码的某个地方使用时:

self.fileName = @"ciao";

你正在使用属性setter方法,就像你直接调用它一样(你可以这样做,隐形方法setFileName:真的存在):

[self setFileName:@"ciao"];

这样做,正如你在setter方法中看到的那样,从现在开始就保留了fileName,所以你应该在dealloc中释放它。

但是,回答你的问题:

如果您使用点规则在var中设置一个新字符串,那么一切都很好, 但是你可能决定以某种标准的方式设置它,可能只是为了错误:

    fileName = @"ciao";
    // code
    fileName = @"Hallo";
    // code
    fileName = @"Bye";

这种方式你没有使用属性setter方法,但你直接使用var,所以不保留fileName,如果你试图释放它,那么你可能会崩溃...

PS: 手动判断retainCount?

不,永远不要那样做

答案 1 :(得分:2)

是的,它们应始终在dealloc中发布。如果你得到dealloc并且某些内容已经发布但未设置为nil那么你在应用程序的其他地方的内存管理方面做错了。

技术上在dealloc中你不需要在发布后设置为nil,但在发布后设置为nil通常是个好主意。

答案 2 :(得分:2)

您的dealloc不必要地为每个属性调用getter,然后立即释放它。只需指定nil即可发布属性:

- (void)dealloc {   

    self.checkedImageView = nil;
    self.fileName = nil;
    self.fullSizeImage = nil;
    self.thumbnailImage = nil;

    [super dealloc];
}

虽然如果你遵循让clang自动生成你的支持实例变量的当前趋势,那么这更好,因为它不会导致KVO副作用:

- (void)dealloc {   

    [_checkedImageView release];
    [_fileName release];
    [_fullSizeImage release];
    [_thumbnailImage release];

    [super dealloc];
}

答案 3 :(得分:0)

是的,它们通常都应该被释放。如果你的保留计数为零,那通常意味着你在内存管理代码中的某个地方犯了一个错误。

你问:如果没有,我怎么知道什么时候发布,什么时候不发布?手动判断retainCount?

可能,但您也可以使用静态分析让Xcode帮助您。转到Product -> Analyze。它经常会帮助您找到错误的版本等。

答案 4 :(得分:0)

何时发布?很明显,如果你的对象持有对另一个对象的引用,并且你的对象消失了,那么它应该停止对另一个对象的引用。你为什么要查看保留计数?保留计数是关于持有相同对象的其他人,但它们不属于您的业务。他们应该知道他们在做什么。所以释放对象。你做你的工作;其他人都必须做他们的。正如其他人所说,最简单的方法就是分配

self.someproperty = nil;

如果你的对象是唯一一个持有引用的对象,那么另一个对象就会消失。如果其他人有参考,它就不会消失。正如每个人都期望的那样。 "发布"方法应该是唯一一个关心对象的保留计数的人。