0

我曾经这样做,直到我发现我的保留属性之一的保留计数在 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];
}
4

5 回答 5

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?

不,永远不要那样做

于 2013-05-23T09:00:12.257 回答
2

是的,它们应该始终以dealloc. 如果你去 dealloc 并且某些东西已经被释放并且没有设置,nil那么你在应用程序的其他地方的内存管理有问题。

从技术上讲,dealloc您不需要nil在发布后设置为,但在发布后设置为零通常是一个好主意。

于 2013-05-23T07:46:30.383 回答
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];
}
于 2013-05-23T07:55:51.400 回答
0

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

self.someproperty = nil;

如果您的对象是唯一持有引用的对象,则另一个对象将消失。如果其他人持有参考,它不会消失。正如每个人所期望的那样。“释放”方法应该是唯一关心对象保留计数的方法。

于 2014-03-14T11:08:57.967 回答
0

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

你问:如果不是,我怎么知道什么时候放,什么时候不放?手动判断retainCount?

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

于 2013-05-23T07:52:08.973 回答