我已将我的属性设置为保留,即使它设置为自动释放,我是否也应该释放它?
假设我们有一些如下所示的代码:
@interface SomeClass : NSObject
@property (nonatomic, retain) NSString *someString;
@end
@implementation SomeClass
@synthesize someString;
-(id)init {
if (self=[super init]) {
someString = [NSString stringWithString:@"some string"];
}
return self;
}
@end
我是否应该在 SomeClass
的 dealloc 方法中释放 someString
属性,即使 someString
> 被设置为 autorelease,但我实际上从未将其保留在我的 init
方法中?如果是这样,我只需在 -release
方法中的 [super dealloc]
之前添加 [someString release]
即可。正确的?
现在我遇到的真正问题是,在使用 Cocos2D 时,我遇到了矛盾的情况。我的代码如下所示:
@interface SomeLayer : CCLayer
@property (nonatomic, retain) CCSprite *someSprite;
@end
@implementation SomeLayer
@synthesize someSprite;
-(id)init {
if (self=[super init]) {
someSprite = [CCSprite spriteWithFile:@"SomeFile.png"];
[self addChild:someSprite];
}
return self;
}
@end
现在,我已将 someSprite
作为子层添加到我的图层 SomeLayer
中。那么,我应该怎么做才能确保这里没有内存泄漏呢?我可以想到以下内容:
- 显然,我会考虑在
SomeLayer
的-dealloc
方法中调用[someSprite release]
。但它在[super dealloc]
(下一行)中给了我EXC_BAD_ACCESS
。最有可能的是因为我没有删除孩子,而超类尝试访问我刚刚释放的孩子。 - 我在
-dealloc
方法中调用[self removeChild:someSprite cleanup:YES]
,这将删除子级并释放它。所以我不需要跟进[someSprite release]
。但是,嘿,超类CCNode
的-dealloc
方法已经为我完成了这一切。 - 我什么也不做。我根本不会重写
-dealloc
方法。嗯,这似乎工作正常,但它与以下说法相矛盾:“如果你保留某些东西,你应该释放它”。
从长远来看,任何关于为什么我必须在情况一中释放对象以及为什么在情况二中不尽早释放对象的帮助都将有助于避免大量与内存相关的问题。
谢谢
Let us say we have some code that looks like below:
@interface SomeClass : NSObject
@property (nonatomic, retain) NSString *someString;
@end
@implementation SomeClass
@synthesize someString;
-(id)init {
if (self=[super init]) {
someString = [NSString stringWithString:@"some string"];
}
return self;
}
@end
Am I supposed to release the someString
property in the dealloc method of SomeClass
, even if someString
was set to autorelease and I never actually retained it in my init
method? If so, I'd simply add [someString release]
before [super dealloc]
in the -release
method. Correct?
Now the real issue I am having is that while using Cocos2D, I've reached a contradicting situation. My code looks like below:
@interface SomeLayer : CCLayer
@property (nonatomic, retain) CCSprite *someSprite;
@end
@implementation SomeLayer
@synthesize someSprite;
-(id)init {
if (self=[super init]) {
someSprite = [CCSprite spriteWithFile:@"SomeFile.png"];
[self addChild:someSprite];
}
return self;
}
@end
Now, I have added someSprite
as a child to my layer SomeLayer
. So, what should I do to make sure I have no memory leaks here? I could think of the following:
- Obviously, I'd think of calling
[someSprite release]
inSomeLayer
's-dealloc
method. but it gives meEXC_BAD_ACCESS
in[super dealloc]
(the next line). Most likely because I didn't remove the child, and the superclass tries to access the child that I just released. - I call
[self removeChild:someSprite cleanup:YES]
in the-dealloc
method, which would remove the child and also release it. So I do not need to follow up with[someSprite release]
. But hey, the-dealloc
method of the superclassCCNode
already does all that for me. - I do nothing. I wouldn't override the
-dealloc
method at all. Well, this seems to work fine, but it contradicts the statement: "if you retain something, you're supposed to release it".
Any help on why I must release the object in case I, and why not in case II at an early stage would help save a lot of memory related issues in the long run.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是错误的。您保留了一个指向自动释放对象的指针,该对象很快就会消失,当您尝试使用 someString 指针时,就会发生不好的事情。您应该使用访问器 (
[self setSomeString:…]
)、保留自动释放的值 (someString = […retain]
) 或使用返回保留值的方法 (someString = [[NSString alloc] init…]
)。在您的实际用例中,您应该对精灵执行相同的操作,您将获得
EXC_BAD_ACCESS
因为您过度释放了精灵:您调用release
而不保留该值。阅读 Cocoa 内存管理指南,您将为自己节省从长远来看会带来很多麻烦。顺便说一句,我认为您的主要问题是您认为对
someString
变量的简单赋值保留了分配的值。事实并非如此(更准确地说,没有 ARC 就不是这样)。对实例变量的赋值就是一个简单的赋值。如果您想访问访问器,则必须发送消息 ([self setSomeString:…]
) 或使用点符号 (self.someString = …
)。This is wrong. You are keeping a pointer to an autoreleased object that will disappear soon, and when you’ll try to use the
someString
pointer bad things will happen. You should use the accessor ([self setSomeString:…]
), retain the autoreleased value (someString = [… retain]
) or use a method that returns a retained value (someString = [[NSString alloc] init…]
).In your real use case you should do the same with the sprite, you are getting
EXC_BAD_ACCESS
because you over-release the sprite: you callrelease
without ever retaining the value. Read the Cocoa Memory Management Guide, you will save yourself a lot of trouble in the long run.By the way, I think your main problem is that you think that a simple assignment to the
someString
variable retains the assigned value. That is not the case (not without ARC, to be more precise). Assignment to the instance variable is just that, a plain assignment. If you want to go through the accessors, you have to send a message ([self setSomeString:…]
) or use the dot notation (self.someString = …
).您只需释放显式分配的对象。您给出的示例都没有被分配,因此它们是自动释放的。如果你想长期保留一个自动释放的对象,你需要保留它,然后才需要释放该对象。
此外,如果您有属性,则应在 viewDidUnload 中将它们设置为 nil
self.someString = nil;
You only have to release objects that you explicitly allocate. None of the examples you gave were allocated, so they are autoreleased. If you want to keep an autoreleased object for a long period of time, you need to retain it, and only then you would need to release the object.
Additionally, if you have properties you should set them to nil in
viewDidUnload
self.someString = nil;
你真的需要阅读内存管理编程指南< /a>.
四个规则中有两个
当您将属性声明为
retain
时,您应该为适当的变量调用release
。在您的情况下,您的 dealloc 应该看起来并查看此代码
为了避免这种情况,您需要保留新创建的精灵
You really need to read Memory Management Programming Guide.
There are two of four rules
When you declare property as
retain
then you should callrelease
for appropriate variable. In your case your dealloc should looksAnd look at this code
To avoid this you need to retain newly created sprite
这一行使 SomeSprite 的保留计数为 1..在 dealloc 中释放它,因此保留又回到 0.. 对象释放。
这是一个自动释放对象..
当你这样做时,
你将 someSprite 指向自动释放对象..所以现在两者相等..
这一行弄乱了合成(保留)的整个点..所以现在将此行更改为
现在你只需继续就是这样..在dealloc中释放
someSprite release
..一切都会好起来的this line makes the retain count of SomeSprite to 1 ..in dealloc you release it so retain is back to 0.. object release.
this is an autorelease object..
when you do
you point someSprite to the autorelease object.. so both are now equal..
this line messes the whole point of synthesize(retain) ..so now change this line to
now you just continue the way it was.. have
someSprite release
in the dealloc.. and everything will be good again