关于iphone:@ property / @综合问题

@property/@synthesize question

我正在阅读关于内存管理的所有文档,我有点困惑。

使用@property时,它会为对象创建getter/setter:

h:@属性(保留,非原子)nScord*MyS字符串

M:@合成字符串

我明白这一点,但我困惑的是自我的使用。我在不同的博客和书籍中看到了不同的语法。我见过:

1
myString = [NSString alloc] initWithString:@"Hi there"];

1
self.myString = [NSString alloc] initWithString:@"Hi there"];

然后在Dealloc中我看到:

1
self.myString = nil;

1
[myString release];

1
2
self.myString = nil;
[myString release];

在这个网站上,有人说使用self会给保留计数增加一个增量?是真的吗,我哪儿也没见过。

是否提供自动释放的自动getter/setter?

这一切的正确方法是什么?

谢谢!


如果不使用点语法,则不使用任何setter或getter。

接下来,它取决于如何声明该属性。

假设如下:

1
2
3
@property (nonatomic, retain) Article *article;
...
@synthesize article;

为文章分配内容

1
self.article = [[Article alloc] init];

将过度保留alloc/init返回的实例并导致泄漏。这是因为文章的设置者将保留它,并将为您释放以前的任何实例。

所以你可以把它改写为:

1
self.article = [[[Article alloc] init] autorelease];

这样做

1
article = [[Article alloc] init];

也可以,但可能涉及泄漏,因为文章可能已经包含了对实例的引用。因此需要提前释放值:

1
2
[article release];
article = [[Article alloc] init];

释放内存可以用

1
[article release];

或与

1
self.article = nil;

第一个直接访问字段,不涉及setter/getter。第二个使用setter将字段设置为nil。如果在将当前实例设置为nil之前有一个实例,它将释放当前实例。

这个构造

1
2
self.myString = nil;
[myString release];

只是太多了,它实际上发送到零释放,这是无害的,但也不必要。

您只需在心理上使用点语法映射帽子,使用访问器方法:

1
2
3
self.article = newArticle
// is
[self setArticle:newArticle];

1
2
3
myArticle = self.article;
// is
myArticle = [self article];

关于阅读的一些建议,苹果公司的所有官方文件:

目标C程序设计语言

  • 点语法
  • 声明的属性

内存管理编程指南

  • 物的所有权和处置
  • 使用访问器方法


除了尼克的回答之外——合成的getter/setter不提供autorelease(顺便说一句,做这个有什么大主意?好吧,可以将getter用作工厂,但在目标C中这不是一种常见的方法)。

Then in dealloc I see:

self.myString = nil;

or

[myString release];

or

self.myString = nil; [myString
release];

在DealLoc中,使用哪种发布形式并不重要。但最好的办法是在释放它们的时候将你的字段置为零:)我更喜欢在dealoc中使用self.myString = nil;


当您创建一个retainsetter时,您正在创建如下内容:

1
2
3
4
5
6
7
- (void)setString:(NSString *)someString {
    if (someString != string) {
        [string release];
        [someString retain];
        string = someString;
    }
}

如果不使用setter,则新值不会得到保留值,也不会"拥有"该字符串,因为它是所有引用,如果释放原始字符串,则可能会面临空引用,这将导致EXC_BAD_ACCESS。使用setter可以确保类现在拥有该值的副本,因此是的,它确实会增加新值的保留计数。(请注意,使用getter是OOP的一种惯例,外部人员不应该直接接触到IVAR。同样,在getter中,您可以修改该值,例如,当您的ivar是一个nsmutablearray时,可能返回一个nsarray)。

你不应该在setter中使用autorelease,苹果在他们的示例代码中使用了它,但要记住的是setter有可能被称为数百万次。所有这些对象都将进入同一个自动释放池,因此除非您创建自己的和/或定期刷新它,否则池中会有大量元素,这些元素都是不需要的,但仍然占用RAM。更简单的说是release

至于dealloc,请通过该setter进行跟踪。如果你直接发送一个release,很明显你释放了这个对象。但如果你写信给self.string = nil;,你要做的是:

  • nil值不相同,因此输入if
  • 你释放旧的价值你想做的
  • 你说"0"[0]nil:发送给nil的消息什么也不做,你不会崩溃。
  • 您将不占用任何内存的nil设置为字符串,该字符串现在实际上是空的。
  • 根据惯例,我在我的dealloc方法中使用release,因为release似乎更为最终,而dealloc是调用你的对象将接收的最终方法。我在viewdidUnload和内存警告方法中使用了self.string = nil;

    希望这有帮助!