2012-03-08 28 views
3

我正在開發一款適用於iOS的紙牌遊戲,並且我遇到了我所猜測的Objective-C中的內存管理問題,我可以不知道。我已經多次閱讀了內存管理,並且我認爲我做的都是正確的,但是每當我嘗試從我的卡片類中調出屬性時,我都會崩潰。Obj-C/Cocos2d內存問題,調用屬性時的exc_bad_access

它的工作方式是我有一個叫做甲板的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); 

} 

}

沒有骰子。 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方法(現在 - 剛剛添加的分配/初始化,看看它是否會工作):由請求添加

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

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

} 
return self; 
} 

這裏的產品名稱:

-(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; 

} 
+0

你可以顯示你的classe聲明和你的init方法嗎? – 2012-03-08 09:49:08

+0

你可以通過激活NSZombie來了解它是否是一個解除分配的實例:如果你的卡片是一個殭屍,你在xcode中有一個Exc_bad_access檢查。 – 2012-03-08 09:50:08

+0

卡只是傳遞給「showCards」方法的數組。在遇到問題的情況下,它只是甲板陣列。 – toucansamurai 2012-03-08 09:59:31

回答

3

我認爲你會在屬性和實例變量之間混合起來。實例變量是引用對象的東西,而屬性只是分配給它們並獲取它們的一種奇特方式。

如果您有:

name = cardName; 

這是什麼東西做的是分配給稱爲name實例變量。這是而不是分配給屬性 - 這是用點語法完成的 - self.name = cardName。代碼會發生什麼情況,因爲您將失去對實例變量中任何現有對象的引用 - 從而泄漏內存 - 並且對新對象的引用將置於其位置。但是,如果你看看新對象來自何處:

NSString *cardName = [NSString stringWithFormat:... 

...你會看到它是自動釋放的。所以沒有任何東西能夠保留這個對象,並且在未來某個時候它將被釋放。你仍然有一個對內存位置的引用,但是它不會包含你想要的對象 - 這是一個懸掛指針,並且可能是你崩潰的原因。

現在,如果我們切換到使用點語法:

self.name = cardName; 

...這裏所發生相當於[self setName:cardName];這是你@synthesize生成的方法。此方法將自動釋放當前存儲在實例變量中的對象並保留新對象,因爲您聲明該屬性爲retain

+0

這是非常好的見解,事實上,將名稱分配固定爲點語法也可以修復崩潰。我會閱讀ivars和財產 - 你是對的,我有一些麻煩,確切地理解其中的差異。有時間弄清楚。非常感謝您的幫助,非常感謝。 – toucansamurai 2012-03-08 16:59:04