Objective c Obj-C/Cocos2d内存问题,调用属性时执行错误访问

Objective c Obj-C/Cocos2d内存问题,调用属性时执行错误访问,objective-c,ios,memory-management,exc-bad-access,Objective C,Ios,Memory Management,Exc Bad Access,我正在为iOS开发一款纸牌游戏,我猜在Objective-C中遇到了一个内存管理问题,我就是搞不懂。我已经读了很多次关于内存管理的书,我认为我做的一切都是对的,但是每当我试图从我的卡片类中调用一个属性时,我就会让游戏崩溃 它的工作方式是我有一个名为deck的NSMutableArray,这是我在Cocos2d中使用的CCLayer的一个属性。我在层的init方法中分配并初始化牌组,然后调用一个方法来填充牌组中的牌: int i; int j; NSString *suit; for (i =

我正在为iOS开发一款纸牌游戏,我猜在Objective-C中遇到了一个内存管理问题,我就是搞不懂。我已经读了很多次关于内存管理的书,我认为我做的一切都是对的,但是每当我试图从我的卡片类中调用一个属性时,我就会让游戏崩溃

它的工作方式是我有一个名为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];

    }

}
它们都是合成的,我甚至试着在卡片的init方法中分配和初始化它们(我认为我不需要这样做,但无论如何都尝试过)

然而,第二次我尝试调用卡的属性:

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

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

    Card *card = [cards objectAtIndex:i];

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

}
init方法(目前——只是添加了alloc/init以查看它是否有效):

以下是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;

}

我觉得你把属性和实例变量搞混了。实例变量是引用对象的对象,而属性只是分配给它们并获取它们的一种奇特方式

如果您有:

name = cardName;
这样做的目的是为名为
name
的实例变量赋值。它没有分配给属性-这是通过点语法完成的-
self.name=cardName
。当前代码的情况是,您将丢失对实例变量中任何现有对象的引用,从而导致内存泄漏,对新对象的引用将被替换。但是,如果您查看新对象的来源:

NSString *cardName = [NSString stringWithFormat:...
…您将看到它是自动释放的。因此没有任何东西可以保留该对象,它将在将来的某个时候被释放。您仍然有一个对内存位置的引用,但它不会包含您希望它包含的对象-这是一个悬空指针,可能是导致崩溃的原因

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

self.name = cardName;

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

您可以显示您的类声明和init方法吗?您可以通过激活NSZombie来了解它是否是一个释放实例:当您在xcode中进行Exc\u bad\u访问检查时,您的卡是否是一个僵尸。cards就是传递给“showCards”方法的任何数组。在我遇到问题的情况下,这只是一个数据组数组。记录一个或多个数据卡似乎都可以正常工作——它们输出的是标准的ObjC对象符号。但是应用程序仍然在card.name日志行中断。您应该始终使具有可变子类(例如NSString)的对象使用
copy
属性类型,而不是
retain
。这是一个极好的洞察,实际上,将名称分配修复为dot语法也修复了崩溃。我会仔细阅读IVAR和属性——你是对的,我很难理解到底有什么区别。是时候弄清楚了。非常感谢你的帮助,非常感谢。
name = cardName;
NSString *cardName = [NSString stringWithFormat:...
self.name = cardName;