我已将我的属性设置为保留,即使它设置为自动释放,我是否也应该释放它?

发布于 2024-12-28 15:22:08 字数 1712 浏览 3 评论 0原文

假设我们有一些如下所示的代码:

@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 中。那么,我应该怎么做才能确保这里没有内存泄漏呢?我可以想到以下内容:

  1. 显然,我会考虑在 SomeLayer-dealloc 方法中调用 [someSprite release] 。但它在[super dealloc](下一行)中给了我EXC_BAD_ACCESS。最有可能的是因为我没有删除孩子,而超类尝试访问我刚刚释放的孩子。
  2. 我在 -dealloc 方法中调用 [self removeChild:someSprite cleanup:YES] ,这将删除子级并释放它。所以我不需要跟进[someSprite release]。但是,嘿,超类 CCNode-dealloc 方法已经为我完成了这一切。
  3. 我什么也不做。我根本不会重写 -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:

  1. Obviously, I'd think of calling [someSprite release] in SomeLayer's -dealloc method. but it gives me EXC_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.
  2. 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 superclass CCNode already does all that for me.
  3. 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 技术交流群。

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

发布评论

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

评论(4

心安伴我暖 2025-01-04 15:22:08
someString = [NSString stringWithString:@"some string"];

这是错误的。您保留了一个指向自动释放对象的指针,该对象很快就会消失,当您尝试使用 someString 指针时,就会发生不好的事情。您应该使用访问器 ([self setSomeString:…])、保留自动释放的值 (someString = […retain]) 或使用返回保留值的方法 ( someString = [[NSString alloc] init…])。

在您的实际用例中,您应该对精灵执行相同的操作,您将获得 EXC_BAD_ACCESS 因为您过度释放了精灵:您调用 release 而不保留该值。阅读 Cocoa 内存管理指南,您将为自己节省从长远来看会带来很多麻烦。

顺便说一句,我认为您的主要问题是您认为对 someString 变量的简单赋值保留了分配的值。事实并非如此(更准确地说,没有 ARC 就不是这样)。对实例变量的赋值就是一个简单的赋值。如果您想访问访问器,则必须发送消息 ([self setSomeString:…]) 或使用点符号 (self.someString = …)。

someString = [NSString stringWithString:@"some string"];

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 call release 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 = …).

盗梦空间 2025-01-04 15:22:08

您只需释放显式分配的对象。您给出的示例都没有被分配,因此它们是自动释放的。如果你想长期保留一个自动释放的对象,你需要保留它,然后才需要释放该对象。

此外,如果您有属性,则应在 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;

爱给你人给你 2025-01-04 15:22:08

你真的需要阅读内存管理编程指南< /a>.


四个规则中有两个

  • 您可以使用retain 获取对象的所有权。
  • 当您不再需要它时,您必须放弃您拥有的对象的所有权

当您将属性声明为 retain 时,您应该为适当的变量调用 release 。在您的情况下,您的 dealloc 应该看起来

- (void)dealloc
    [someSprite release];
    [super dealloc];
}

并查看此代码

 if (self=[super init]) {
        someSprite = [CCSprite spriteWithFile:@"SomeFile.png"]; // here you assign pointer to new object
        [self addChild:someSprite]; // all right, you can use newly created object in this scope
    }
 // but here that object can be deleted from memory and someSprite can points to nothing

为了避免这种情况,您需要保留新创建的精灵

someSprite = [[CCSprite spriteWithFile:@"SomeFile.png"] retain];

You really need to read Memory Management Programming Guide.


There are two of four rules

  • You can take ownership of an object using retain.
  • When you no longer need it, you must relinquish ownership of an object you own

When you declare property as retain then you should call release for appropriate variable. In your case your dealloc should looks

- (void)dealloc
    [someSprite release];
    [super dealloc];
}

And look at this code

 if (self=[super init]) {
        someSprite = [CCSprite spriteWithFile:@"SomeFile.png"]; // here you assign pointer to new object
        [self addChild:someSprite]; // all right, you can use newly created object in this scope
    }
 // but here that object can be deleted from memory and someSprite can points to nothing

To avoid this you need to retain newly created sprite

someSprite = [[CCSprite spriteWithFile:@"SomeFile.png"] retain];
恍梦境° 2025-01-04 15:22:08
@synthesize someSprite;

这一行使 SomeSprite 的保留计数为 1..在 dealloc 中释放它,因此保留又回到 0.. 对象释放。

[CCSprite spriteWithFile:@"SomeFile.png"];

这是一个自动释放对象..

当你这样做时,

someSprite = [CCSprite spriteWithFile:@"SomeFile.png"];

你将 someSprite 指向自动释放对象..所以现在两者相等..

这一行弄乱了合成(保留)的整个点..所以现在将此行更改为

[self setsomeSprite] =[CCSprite spriteWithFile:@"SomeFile.png"];

现在你只需继续就是这样..在dealloc中释放someSprite release..一切都会好起来的

@synthesize someSprite;

this line makes the retain count of SomeSprite to 1 ..in dealloc you release it so retain is back to 0.. object release.

[CCSprite spriteWithFile:@"SomeFile.png"];

this is an autorelease object..

when you do

someSprite = [CCSprite spriteWithFile:@"SomeFile.png"];

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

[self setsomeSprite] =[CCSprite spriteWithFile:@"SomeFile.png"];

now you just continue the way it was.. have someSprite release in the dealloc.. and everything will be good again

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