在Init中调用方法时,Cocos2d项目崩溃:

时间:2011-07-17 06:52:50

标签: iphone objective-c xcode cocos2d-iphone

我正在尝试通过构建一个简单的纸牌游戏来试验cocos2d。我不是iOS开发的新手,但我对cocos2d引擎很新。到目前为止,我有2个自定义类:

卡片类: .H

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface Card : NSObject {
CCSprite *faceSprite;
NSString *suit;
NSUInteger value;
float priority;
}

@property (nonatomic, retain) CCSprite *faceSprite;
@property (nonatomic, readonly) NSString *suit;
@property (nonatomic, readonly) NSUInteger value;
@property (nonatomic, assign) float priority;

- (id)initWithSprite:(CCSprite *)paramSprite suit:(NSString *)paramSuit andValue:(NSUInteger)paramValue;

@end

的.m

#import "Card.h"

@implementation Card
@synthesize faceSprite, suit, value, priority;

- (id)init
{
self = [self initWithSprite:nil suit:nil andValue:nil];
if (self) {
    // Initialization code here.
}

return self;
}

-(id)initWithSprite:(CCSprite *)paramSprite suit:(NSString *)paramSuit andValue:(NSUInteger)paramValue {
if ((self = [super init])) {
    faceSprite = paramSprite;
    suit = paramSuit;
    value = paramValue;
}

return  self;
}

@end

和甲板课: .H

#import <Foundation/Foundation.h>
#import "Card.h"

@interface Deck : NSObject {
NSMutableArray *cardsArray;
}
@property (nonatomic, retain) NSMutableArray *cardsArray;

-(void)shuffle;
-(Card *)drawTopCard;

@end

的.m

- (id)init
{
if ((self = [super init])) {
    cardsArray = [[NSMutableArray alloc] init];
    for (NSInteger suit = 1; suit < 5; suit++) {
        NSString *suitString;
        switch (suit) {
            case 1:
                suitString = @"h";
                break;
            case 2:
                suitString = @"d";
                break;
            case 3:
                suitString = @"s";
                break;
            case 4:
                suitString = @"c";
                break;
        }
        for (NSInteger i = 3; i < 14; i++) {
            CCSprite *cardImage = [CCSprite spriteWithFile:[NSString stringWithFormat:@"%d%@.gif",i, suitString]];
            Card *card = [[Card alloc] initWithSprite:cardImage suit:suitString andValue:i];
            [cardsArray addObject:card];
        }

    }
}

return self;
}

-(void)shuffle {
int timesToShuffle = 1;
while (++timesToShuffle < 4) {
    for (int i = 0; i < [cardsArray count]; i++) {
        int cardToSwap = arc4random() % [cardsArray count];
        [cardsArray exchangeObjectAtIndex:i withObjectAtIndex:cardToSwap];
    }
}

}

-(Card *)drawTopCard {
Card *cardDrawn = [[cardsArray objectAtIndex:0] retain];
//[cardsArray removeObjectAtIndex:0];
return cardDrawn;
}

@end

当我尝试在主场景中执行以下操作时,我在更新中的CCScheduler.m中出现了EXC_BAD_ACCESS错误:(ccTime)方法

-(id) init
{
if( (self=[super init])) {

    deck = [[Deck alloc] init];
    [deck shuffle];
    [self schedule:@selector(drawAndShowCard) interval:3.0];

}
return self;
}

-(void)drawAndShowCard {
// ask director the the window size
CGSize size = [[CCDirector sharedDirector] winSize];

// position the label on the center of the screen
Card *card = [deck drawTopCard];
CCSprite *cardSprite = (CCSprite *)card.faceSprite;
cardSprite.position =  ccp( size.width /2 , size.height/2 );

[self addChild:cardSprite];
}

奇怪的是,如果我在drawCardAndShow方法中移动了deck alloc和shuffle,它就不会再崩溃了,但是由于出于明显的原因,这不是正确的地方,因为我不想每次都有一个全新的套牌我画了一张卡片......

任何帮助?

2 个答案:

答案 0 :(得分:2)

我发现了一个严重的问题,但您的代码存在多个问题。

当你有字符串作为属性时,你应该将它们声明为副本,在你的情况下你将它作为赋值:

@property (nonatomic, readonly) NSString *suit;

如果要以只读方式声明属性,可以再次在.m中声明该属性,使其在内部可写:

@interface Card() 
@property (nonatomic, copy)
NSString *suit; 
@end

当您访问ivar和访问该属性时,您应该使用属性的self.表示法让其他人明白您的意图。

你在这里遇到了一个漏洞:

Card *card = [[Card alloc] initWithSprite:cardImage suit:suitString andValue:i];
            [cardsArray addObject:card];
-->missing [card release]

这是不必要的

@interface Deck : NSObject {
NSMutableArray *cardsArray;
}
@property (nonatomic, retain) NSMutableArray *cardsArray;

您可以省略ivar,只需确保在没有自动释放的情况下不分配/ init。

如果你坚持要将ivar重命名至少_cardsArray然后再

@synthesize cardsArray=_cardsArray

这样你就可以区分这两者了。在一种情况下,你需要明确保留,在另一种情况下你需要使用setter / getter。

HTH

答案 1 :(得分:1)

你应该将deck设为属性