Obj-C / Cocos2d内存问题,调用属性时的exc_bad_access

时间:2012-03-08 09:46:39

标签: objective-c ios memory-management exc-bad-access

我正在开发一款适用于iOS的纸牌游戏,而且我遇到的是我猜测的Objective-C中的内存管理问题,这是我无法弄清楚的。我已经多次阅读内存管理,我认为我做的一切都是正确的,但每当我尝试从我的Card类中调出一个属性时,我就会让游戏崩溃。

它的工作方式是我有一个名为deck的NSMutableArray,它是我在Cocos2d中使用的CCLayer的属性。我在图层的init方法中分配并初始化套牌,然后调用一个方法来填充套牌中的卡片:

int i;
int j;
NSString *suit;

for (i = 0; i < 4; i++) {

    switch (i) {
        case 0:
            suit = @"Hearts";
            break;
        case 1:
            suit = @"Clubs";
            break;
        case 2:
            suit = @"Spades";
            break;
        case 3:
            suit = @"Diamonds";
            break;
    }


    for (j=1; j < 15; j++) {

        Card *card = [[Card alloc] init];
        card.suit = suit;
        card.rank = j;
        [card makeName];
        [deck addObject:card];

    }

}

在Card类中,我有属性:

@property (nonatomic, retain) NSString *suit;
@property (nonatomic, retain) NSString *name;
@property (nonatomic) int rank;

每个都是合成的,我甚至尝试在Card的init方法中分配和启动它们(我认为我不需要这样做,但无论如何都要尝试)。

第二次我试着打电话给卡的财产,但是:

-(void) showCards: (NSMutableArray *) cards {

for (int i = 0; i < [cards count]; i++) {

    Card *card = [cards objectAtIndex:i];

    NSLog(@"%@",card.name);

}

}

没有骰子。 EXC_BAD_ACCESS。我的猜测是,在我使用它们之前,这些卡片已经以某种方式解除分配,但我已经做了一切让我们能够想到的东西。有什么想法吗?我猜这很简单,我误解了,但我没有想法。谢谢!

编辑:按要求添加:

班级声明:

@interface Card : NSObject {

//NSString *suit;
//int rank;
//NSString *name;

}

property (nonatomic, retain) NSString *suit;
property (nonatomic, retain) NSString *name;
property (nonatomic) int rank;'

init方法(现在 - 只需添加alloc / init以查看它是否可行):

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

    suit = [NSString new];
    rank = 0;
    name = [NSString new];

}
return self;
}

这是makeName:

-(void) makeName {

NSString *rankString;

switch (rank) {
case 1:
        rankString = @"One";
        break;
    case 2:
        rankString = @"Two";
        break;
    case 3:
        rankString = @"Three";
        break;
    case 4:
        rankString = @"Four";
        break;
    case 5:
        rankString = @"Five";
        break;
    case 6:
        rankString = @"Six";
        break;
    case 7:
        rankString = @"Seven";
        break;
    case 8:
        rankString = @"Eight";
        break;

    case 9:
        rankString = @"Nine";
        break;
    case 10:
        rankString = @"Ten";
        break;
    case 11:
        rankString = @"Jack";
        break;
    case 12:
        rankString = @"Queen";
        break;
    case 13:
        rankString = @"King";
        break;
    case 14:
        rankString = @"Ace";
        break;
}

NSString *cardName = [NSString stringWithFormat:@"%@ of %@", rankString, self.suit];

name = cardName;

}

1 个答案:

答案 0 :(得分:3)

我认为你在属性和实例变量之间有点混淆。实例变量是引用对象的内容,而属性只是分配给它们并获取它们的一种奇特方式。

你在哪里:

name = cardName;

这是做什么的,分配给名为name的实例变量。 分配给属性 - 使用点语法 - self.name = cardName完成。代码将会发生的情况是,您将丢失对实例变量中现有对象的引用 - 从而泄漏内存 - 并且将对新对象的引用放在其位置。但是如果你看一下新对象的来源:

NSString *cardName = [NSString stringWithFormat:...

...你会看到它是自动释放的。因此,没有任何东西可以保留该对象,并且它将在未来的某个时候被解除分配。你仍然会有一个对内存位置的引用,但它不会包含你想要它的对象 - 这是一个悬空指针和崩溃的可能原因。

现在,如果我们切换到使用点语法:

self.name = cardName;

...此处发生的事情等同于[self setName:cardName];这是您使用@synthesize生成的方法。此方法将自动释放您当前存储在实例变量中的对象并保留新对象,因为您将该属性声明为retain