@property/@synthesize问题
我正在浏览所有有关内存管理的文档,但我对某些事情有点困惑。
当您使用 @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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您不使用点语法,则您不会使用任何 setter 或 getter。
接下来的事情是,这取决于财产的申报方式。
让我们假设这样的事情:
分配某些内容
将过度保留由 alloc/init 返回的实例并导致泄漏。这是因为文章的设置者将保留它并为您释放任何先前的实例。
因此,您可以将其重写为:
这样做
也可以,但可能会涉及泄漏,因为文章可能已经包含对实例的引用。因此需要提前释放该值:
释放内存可以通过
或 with
来完成第一个确实直接访问该字段,不涉及设置器/获取器。第二个通过使用 setter 将 nil 设置为该字段。如果在将其设置为 nil 之前存在一个实例,则这将释放当前实例。
这个构造
实在是太多了,它实际上将释放发送到nil,这是无害的,但也是不必要的。
你只需要在心里映射使用点语法就是使用访问器方法:
和
一些阅读建议,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:
Assigning something to article with
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:
Doing this
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:
Freeing memory could be done with
or with
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
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:
and
Some suggestions on reading, all official documents by Apple:
The Objective-C Programming Language
Memory Management Programming Guide
当您创建一个
retain
setter 时,您将创建如下内容:如果您不使用该 setter,则新值不会获得该保留 — 您不“拥有”该字符串,而且因为都是引用,如果原始字符串被释放,您可能会面临空引用,这将导致
EXC_BAD_ACCESS
。使用 setter 可确保您的类现在拥有该值的副本 - 所以,是的,它确实会增加新值的保留计数。 (请注意,使用 getter 是 OOP 的约定,即外部人员不应该能够直接接触 ivar。此外,在 getter 中,您可以修改值,例如,当您的 ivar 是 NSMutableArray 时,可能会返回 NSArray)。您不应该在 setter 中自动释放 - Apple 已在其示例代码中使用它,但要记住的一点是 setter 被调用很多次 - 可能有数百万次。所有这些对象都会进入同一个自动释放池,因此除非您创建自己的和/或定期刷新它,否则池中将有大量元素,所有元素都不需要,但仍然占用 RAM。最好简单地
发布
。至于dealloc,可以追溯到那个setter。如果您直接发送
release
,很明显,您释放了该对象。但如果你写self.string = nil;
,你所做的就是这样:if
块保留
nil:发送给 nil 的消息什么都不做,你也不会崩溃,到现在实际上 约定,我在
dealloc
方法中使用release
,因为release
看起来更最终,而dealloc
是最终方法调用你的对象将会收到。我在 viewDidUnload 和内存警告方法中使用 self.string = nil; 。希望这有帮助!
When you create a
retain
setter, you're creating something like this: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 simplyrelease
.As for dealloc, trace back through that setter. If you send a
release
directly, it's obvious—you release that object. But if you writeself.string = nil;
, what you're doing is this:if
blockretain
nil: messages to nil do nothing, and you don't crashAs a matter of convention, I use
release
in mydealloc
method, becauserelease
seems more final, anddealloc
is the final method call your object will receive. I useself.string = nil;
in viewDidUnload and the memory warning methods.Hope this helps!
除了 Nick 的回答之外 - 合成的 getter/setter 不提供自动释放(顺便说一句,这样做的主要想法是什么?好吧,你可以使用 getter 作为工厂,但这不是 Objective C 中的常见方式)。
在 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).
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