我正在查看有关内存管理的所有文档,我对某些事情感到有些困惑。
使用@property时,它会为对象创建getter / setter:
·H: @property(retain,nonatomic)NSString * myString
的.m: @synthesize myString
我理解这一点,但是我感到困惑的地方是使用自我。我在不同的博客和书籍中看到了不同的语法。我见过:
myString = [NSString alloc] initWithString:@"Hi there"];
或
self.myString = [NSString alloc] initWithString:@"Hi there"];
然后在dealloc中我看到:
self.myString = nil;
或
[myString release];
或
self.myString = nil;
[myString release];
在这个网站上,有人说使用self会为保留计数增加另一个增量?是真的,我没有在任何地方见过。
提供自动释放的自动getter / setter吗?
这是完成所有这些的正确方法吗?
谢谢!
答案 0 :(得分:18)
如果您没有使用点语法,则不使用任何setter或getter。
接下来是,它取决于如何声明属性。
让我们假设这样的事情:
@property (nonatomic, retain) Article *article;
...
@synthesize article;
使用
为文章分配self.article = [[Article alloc] init];
将覆盖alloc / init返回的实例并导致泄漏。这是因为文章的设置者将保留它并将为您释放任何先前的实例。
所以你可以把它重写为:
self.article = [[[Article alloc] init] autorelease];
这样做
article = [[Article alloc] init];
也可以,但可能涉及泄漏,因为文章可能已经拥有对实例的引用。因此,需要事先释放价值:
[article release];
article = [[Article alloc] init];
释放内存可以使用
完成[article release];
或
self.article = nil;
第一个直接访问该字段,不涉及setter / getters。第二个使用setter将nil设置为字段。如果有当前实例,则将其设置为nil。
此构造
self.myString = nil;
[myString release];
太多了,它实际上发送给nil,这是无害的,但也是不必要的。
您只需使用点语法精神映射帽子,使用访问器方法:
self.article = newArticle
// is
[self setArticle:newArticle];
和
myArticle = self.article;
// is
myArticle = [self article];
有关阅读的一些建议,Apple的所有官方文件:
Objective-C编程语言
内存管理编程指南
答案 1 :(得分:1)
当你创建一个retain
setter时,你正在创建这样的东西:
- (void)setString:(NSString *)someString {
if (someString != string) {
[string release];
[someString retain];
string = someString;
}
}
如果您不使用setter,则新值不会保留 - 您不“拥有”该字符串,并且因为它是所有引用,如果原始字符串被释放,您可能面临null引用,这将导致EXC_BAD_ACCESS
。使用setter确保您的类现在具有该值的副本 - 所以是的,它确实增加了新值的保留计数。 (请注意,使用getter是OOP的惯例 - 外人不应该直接触摸ivar。也可以在你的getter中修改值,例如,当你的ivar是NSMutableArray时,可能会返回NSArray)。
你不应该在一个setter中autorelease
- Apple已经在他们的示例代码中使用了它,但要记住的是,setter被称为很多次,可能是。所有这些对象都进入相同的自动释放池,所以除非你创建自己的和/或定期刷新它,你的池中将有大量元素,所有元素都不需要但仍占用RAM。简单地release
就好了。
至于dealloc,追溯那个setter。如果您直接发送release
,很明显 - 您释放该对象。但是如果你写self.string = nil;
,那你正在做的是:
if
块retain
nil:消息为nil什么都不做,你不会崩溃作为惯例,我在release
方法中使用dealloc
,因为release
似乎更为最终,dealloc
是您的对象将收到的最终方法调用。我在viewDidUnload中使用self.string = nil;
和内存警告方法。
希望这有帮助!
答案 2 :(得分:1)
除了Nick的回答 - 合成的getter / setter不提供自动释放(顺便说一句,这样做有什么好主意?好吧,你可以使用getter作为工厂,但它不是Objective C中的常用方法)。
然后在dealloc中我看到:
self.myString = nil;
或
[myString release];
或
self.myString = nil; [myString的 释放];
在dealloc中,您正在使用哪种版本的释放并不重要。但是好的方法是在释放它们时使你的字段为零:)我更喜欢在dealloc中使用self.myString = nil;