Objective c I’;如果已将我的属性设置为“保留”,即使设置为“自动释放”,我是否应该释放它?
假设我们有一些代码如下所示:Objective c I’;如果已将我的属性设置为“保留”,即使设置为“自动释放”,我是否应该释放它?,objective-c,memory-management,cocos2d-iphone,retain,Objective C,Memory Management,Cocos2d Iphone,Retain,假设我们有一些代码如下所示: @interface SomeClass : NSObject @property (nonatomic, retain) NSString *someString; @end @implementation SomeClass @synthesize someString; -(id)init { if (self=[super init]) { someString = [NSString stringWithString:@"some
@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
@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
即使SomeClass
的dealloc方法中的someString
设置为自动释放,并且我从未在init
方法中实际保留它,我是否应该释放someString
属性?如果是这样,我只需在-release
方法中的[someString release]
之前添加[super dealoc]
。对吗
现在我面临的真正问题是,在使用Cocos2D时,我遇到了一个矛盾的情况。我的代码如下所示:
@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
@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
现在,我在我的图层SomeLayer
中添加了someSprite
。那么,我应该做些什么来确保这里没有内存泄漏呢?我可以想到以下几点:
SomeLayer
的-dealoc
方法中调用[someSprite release]
。但是它在[super dealoc]
中为我提供了EXC\u BAD\u访问权限(下一行)。很可能是因为我没有删除子类,而超类试图访问我刚刚发布的子类
-dealloc
方法中调用[self-removeChild:someSprite cleanup:YES]
,这将删除子项并释放它。因此,我不需要跟进[someSprite release]
。但是,超类CCNode
的-dealoc
方法已经为我完成了所有这些-dealoc
方法。好吧,这似乎很有效,但它与“如果你保留了某些东西,你应该释放它”的说法相矛盾someString
指针时,会发生不好的事情。您应该使用访问器([self-setSomeString:…]
),保留自动删除的值(someString=[…retain]
),或者使用返回保留值的方法(someString=[[NSString alloc]init…])
)
在您的实际用例中,您应该对sprite执行相同的操作,因为您过度释放了sprite,所以您将获得EXC\u BAD\u访问
:您调用release
,但从未保留该值。读这本书,从长远来看,你会省去很多麻烦
顺便说一下,我认为您的主要问题是您认为对someString
变量的简单赋值会保留赋值。事实并非如此(更准确地说,没有弧也不行)。对实例变量的赋值就是一个普通赋值。如果你想通过访问器,你必须发送一条消息([self-setSomeString:…]
)或使用点符号(self.someString=…
)
这是错误的。您正在保留一个指向即将消失的自动释放对象的指针,当您尝试使用someString
指针时,会发生不好的事情。您应该使用访问器([self-setSomeString:…]
),保留自动删除的值(someString=[…retain]
),或者使用返回保留值的方法(someString=[[NSString alloc]init…])
)
在您的实际用例中,您应该对sprite执行相同的操作,因为您过度释放了sprite,所以您将获得EXC\u BAD\u访问
:您调用release
,但从未保留该值。读这本书,从长远来看,你会省去很多麻烦
顺便说一下,我认为您的主要问题是您认为对
someString
变量的简单赋值会保留赋值。事实并非如此(更准确地说,没有弧也不行)。对实例变量的赋值就是一个普通赋值。如果你想通过访问器,你必须发送一条消息([self-setSomeString:…]
)或使用点符号(self.someString=…
)。你只需要释放你显式分配的对象。您给出的示例均未分配,因此它们将自动删除。如果要将自动释放的对象保留很长一段时间,则需要保留它,然后才需要释放该对象
此外,如果您有属性,则应在viewDidUnload
self.someString=nil代码>您只需释放显式分配的对象。您给出的示例均未分配,因此它们将自动删除。如果要将自动释放的对象保留很长一段时间,则需要保留它,然后才需要释放该对象
此外,如果您有属性,则应在viewDidUnload
self.someString=nil代码>您确实需要读取内存
有四条规则中的两条
- 您可以使用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];
你真的需要阅读记忆
有四条规则中的两条
- 您可以使用retain获得对象的所有权
- 当您不再需要它时,必须放弃您所拥有的对象的所有权
当您将属性声明为retain
时,您应该调用release
以获取适当的变量。在你的
[CCSprite spriteWithFile:@"SomeFile.png"];
someSprite = [CCSprite spriteWithFile:@"SomeFile.png"];
[self setsomeSprite] =[CCSprite spriteWithFile:@"SomeFile.png"];