问题
I have cocos2d project with custom CCSprite subclass:
MyCustomSprite.h:
#import "cocos2d.h"
@interface MyCustomSprite : CCSprite
@end
MyCustomSprite.m:
#import "MyCustomSprite.h"
@implementation MyCustomSprite
- (id)init
{
self = [super initWithFile:@"index.png"];
return self;
}
@end
For some strange reason, this code will crash with "EXC_BAD_ACCESS".
But in spite of this, if i init super as ususal and then write code from CCSprite's initWithFile and initWithTexture, it will work fine:
self = [super init];
if (self) {
// Code from CCSprite.m - initWithFile
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: @"index.png"];
CGRect rect = CGRectZero;
rect.size = texture.contentSize;
// Code from CCSprite.m - iniWithTexture
[self setTexture:texture];
[self setTextureRect:rect];
return self;
}
What's the reason that the first example crashes, and second not and what's the difference between them?
Thanks for your answers!
回答1:
Ok, the reason is bad CCSprite design. If we look to CCSprite.h, we can find:
-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect
{
NSAssert(texture!=nil, @"Invalid texture for sprite");
// IMPORTANT: [self init] and not [super init];
if( (self = [self init]) )
}
And thats the reason. Instead of [super init]
this method calls [self init]
, and creates recursion ([self init]-[super InitWithFile:]-[self initWithTexture]-[self init]-...)
.
.
So, the simplest way to solve this problem - just re-name your init method to something else (for example "initialize") and call it instead of init: [[MyCustomSprite
alloc] initialize]
.
回答2:
Another approach that may work is just replace your code by this one:
- (id)init
{
self = [super init];
if (self != nil)
{
CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:@"my_image_name.png"];
CGRect rect = CGRectZero;
if (texture != nil)
{
rect.size = texture.contentSize;
}
[self setDisplayFrame:[CCSpriteFrame frameWithTexture:texture rect:rect]];
}
return self;
}
And a simpler way, if you are using CCSpriteFrameCache, would be just setting the display frame by
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"my_image_name.png"]
Hope to help somebody!
来源:https://stackoverflow.com/questions/7293851/cocos2d-ccsprite-initwithfile-in-ccsprite-subclass-crashes