@property/@synthesize问题

发布于 2024-11-05 08:16:32 字数 754 浏览 6 评论 0原文

我正在浏览所有有关内存管理的文档,但我对某些事情有点困惑。

当您使用 @property 时,它会为对象创建 getters/setters:

.h: @property(保留,非原子)NSString *myString

.m: @synthesize myString

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

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 是否会自动释放?

哪种方法是完成所有这一切的正确方法?

谢谢!

I'm going through all of my documentation regarding memory management and I'm a bit confused about something.

When you use @property, it creates getters/setters for the object:

.h:
@property (retain, nonatomic) NSString *myString

.m:
@synthesize myString

I understand that, but where I get confused is the use of self. I see different syntax in different blogs and books. I've seen:

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

or

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

Then in dealloc I see:

self.myString = nil;

or

[myString release];

or

self.myString = nil;
[myString release];

On this site, someone stated that using self adds another increment to the retain count? Is that true, I haven't seen that anywhere.

Do the automatic getters/setters that are provided autorelease?

Which is the correct way of doing all of this?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

再可℃爱ぅ一点好了 2024-11-12 08:16:32

如果您不使用点语法,则您不会使用任何 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];

或 with

self.article = nil;

来完成第一个确实直接访问该字段,不涉及设置器/获取器。第二个通过使用 setter 将 nil 设置为该字段。如果在将其设置为 nil 之前存在一个实例,则这将释放当前实例。

这个构造

self.myString = nil; 
[myString release];

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

你只需要在心里映射使用点语法就是使用访问器方法:

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

myArticle = self.article;
// is
myArticle = [self article];

一些阅读建议,Apple 的所有官方文档:

The Objective-C 编程语言

内存管理编程指南

If you are not using the dot syntax you are not using any setter or getter.

The next thing is, it depends on how the property has been declared.

Let's assume something like this:

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

Assigning something to article with

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

will overretain the instance given back by alloc/init and cause a leak. This is because the setter of article will retain it and will release any previous instance for you.

So you could rewrite it as:

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

Doing this

article = [[Article alloc] init]; 

is also ok, but could involve a leak as article may hold a reference to an instance already. So freeing the value beforehand would be needed:

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

Freeing memory could be done with

[article release];

or with

self.article = nil;

The first one does access the field directly, no setters/getters involved. The second one sets nil to the field by using a setter. Which will release the current instance, if there is one before setting it to nil.

This construct

self.myString = nil; 
[myString release];

is just too much, it actually sends release to nil, which is harmless but also needless.

You just have to mentally map hat using the dot syntax is using accessor methods:

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

and

myArticle = self.article;
// is
myArticle = [self article];

Some suggestions on reading, all official documents by Apple:

The Objective-C Programming Language

Memory Management Programming Guide

十雾 2024-11-12 08:16:32

当您创建一个 retain setter 时,您将创建如下内容:

- (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 中自动释放 - Apple 已在其示例代码中使用它,但要记住的一点是 setter 被调用很多次 - 可能有数百万次。所有这些对象都会进入同一个自动释放池,因此除非您创建自己的和/或定期刷新它,否则池中将有大量元素,所有元素都不需要,但仍然占用 RAM。最好简单地发布

至于dealloc,可以追溯到那个setter。如果您直接发送release,很明显,您释放了该对象。但如果你写 self.string = nil;,你所做的就是这样:

  1. nil 值不一样,所以你进入 if
  2. 你释放旧值——你想做的事情
  3. 保留 nil:发送给 nil 的消息什么都不做,你也不会崩溃
  4. 你设置了 nil,它不占用任何内存 是空的字符串

,到现在实际上 约定,我在 dealloc 方法中使用 release,因为 release 看起来更最终,而 dealloc 是最终方法调用你的对象将会收到。我在 viewDidUnload 和内存警告方法中使用 self.string = nil; 。

希望这有帮助!

When you create a retain setter, you're creating something like this:

- (void)setString:(NSString *)someString {
    if (someString != string) {
        [string release];
        [someString retain];
        string = someString;
    }
}

If you don't use the setter, the new value is not getting that retain—you don't "own" that string, and because it's all references, if the original string is released, you might be facing a null reference, which will lead to an EXC_BAD_ACCESS. Using the setter ensures that your class now has a copy of that value—so yes, it does increment the retain count of the new value. (Note that using the getter is a convention of OOP—that outsiders should not be able to directly touch the ivar. Also in your getter you can modify the value, maybe returning an NSArray when your ivar is an NSMutableArray, for example).

You shouldn't autorelease in a setter—Apple has used it in their sample code, but a thing to keep in mind is that setters are called a lot—millions of times, potentially. All of those objects are going into the same autorelease pool, so unless you create your own and/or regularly flush it, you'll have a ton of elements in your pool, all unneeded but still taking up RAM. Much better to simply release.

As for dealloc, trace back through that setter. If you send a release directly, it's obvious—you release that object. But if you write self.string = nil;, what you're doing is this:

  1. The nil value is not the same, so you enter the if block
  2. You release the old value—what you want to do
  3. You retain nil: messages to nil do nothing, and you don't crash
  4. You set nil, which doesn't take up any memory, to the string, which is now effectively empty

As a matter of convention, I use release in my dealloc method, because release seems more final, and dealloc is the final method call your object will receive. I use self.string = nil; in viewDidUnload and the memory warning methods.

Hope this helps!

半衾梦 2024-11-12 08:16:32

除了 Nick 的回答之外 - 合成的 getter/setter 不提供自动释放(顺便说一句,这样做的主要想法是什么?好吧,你可以使用 getter 作为工厂,但这不是 Objective C 中的常见方式)。

然后在 dealloc 中我看到:

self.myString = nil;

[myString 发布];

self.myString = nil; [我的字符串
发布];

在 dealloc 中,使用哪种形式的释放并不重要。但最好的方法是在释放字段时将其归零:)我更喜欢在 dealloc 中使用 self.myString = nil;

In addition to Nick's answer - synthesized getters/setters don't provide autorelease (btw, what's the big idea of doing this? Well, you can use getter as a factory, but it's not a common way in Objective C).

Then in dealloc I see:

self.myString = nil;

or

[myString release];

or

self.myString = nil; [myString
release];

In dealloc it doesn't really matter which form of release you're using. But the good way is to nil your fields when releasing them :) I prefer to use self.myString = nil; in dealloc

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文