2011-04-19 80 views
0

我在Ojective-C上編寫了一個月並陷入了僵局。需要幫忙。 這裏是故事:一個變量不是CFString

  1. 我有一個簡單的類LXPPlayingCard:

    #import <Cocoa/Cocoa.h> 
    @interface LXPPlayingCard : NSObject { 
    @private NSString* cardCV; 
    @private int position; 
    } 
    
    @property (readwrite, assign) NSString* cardCV; 
    @property (readwrite,assign) int position; 
    @end 
    
    @implementation LXPPlayingCard 
    @synthesize cardCV; 
    @synthesize position; 
    @end 
    
  2. 我也有幾乎沒有更復雜的類LXPDeck:

    #import <Cocoa/Cocoa.h> 
    #import "LXPPlayingCard.h" 
    @interface LXPDeck : NSObject { 
    LXPPlayingCard* cards[100]; 
    int deckCapacity; 
    } 
    
    -(void) fill:(NSString *) cardlist; 
    -(void) showList; 
    -(int) deckCapacity; 
    
    @end 
    
    #import "LXPDeck.h" 
    #import "LXPPlayingCard.h" 
    @implementation LXPDeck 
    -(void) fill:(NSString *) cardlist { 
        int l,i,j; 
        l=[cardlist length]; 
        j=0; 
        for (i=0;i<l;i+=2) { 
         cards[j]=[[LXPPlayingCard alloc] init] ;   
         [cards[j] setCardCV:[cardlist substringWithRange:NSMakeRange(i,2)]]; 
         [cards[j] setPosition:j+1]; 
         NSLog(@"%@",[cards[j] cardCV]); 
         j++; 
        } 
        deckCapacity=j; 
        } 
    
        -(int) deckCapacity { return deckCapacity;} 
    
        -(void) showList { 
        NSLog(@"deck capacity:%d",deckCapacity); 
        NSString * temp; 
        temp=[[NSString alloc] init]; 
        for (int i=0;i<deckCapacity;i++) { 
        NSLog(@"card[%d]=%d, adress:%p",i,[cards[i] position],cards[i]); 
        temp=[cards[i] cardCV]; 
        NSLog(@"%@",temp); 
        } 
        } 
    
    @end 
    

裏面做情侶東西:用字符串填充名稱(setCardCV)的卡片陣列,並打印卡片組的內容(showList )。 此外我創建類AppController的:在其上予連接到openNewDeckprintDeckContent方法的主要窗口

@interface LXPAppController : NSObject { 

} 
-(IBAction) openNewDeck:(NSButton *)sender; 
-(IBAction) printDeckContent:(NSButton *)sender ; 

@end 

#import "AppController.h" 
#import "LXPDeck.h" 


@implementation LXPAppController 
    BOOL deckOpened=FALSE; 
    LXPDeck* workDeck; 

-(IBAction) openNewDeck:(NSButton *) sender{ 

    if (!deckOpened) { 
     NSLog(@"Opening new deck..."); 
     workDeck=[LXPDeck alloc]; 
     [workDeck fill:@"pacataca"]; 
    } 

    deckOpened=TRUE; 
} 
-(IBAction) printDeckContent:(NSButton *) sender { 

    if (deckOpened) { 
     NSLog(@"Printing deck content..."); 
     [workDeck showList]; 
    } 
} 
@end 

和兩個按鈕。 問題是,應用程序下降與錯誤「EXC_BAD_ACCESS」,它發生在i = 3,因爲(當我使用調試器)[card[i] cardCV]不是一個CFString。

我嘗試用不同的字符串填充卡組,有時程序在顯示[cards[i] cardCV]的拳頭圓上失敗。 我真不明白髮生了什麼,但我想它在某種程度上與指針和內存分配規則的連接,因爲沒有簡單類型的數據(position例如)和showList方法沒有問題的正常工作,如果它從fill方法調用。 請給我一隻手!我瘋了!該計劃是如此簡單,我真的很擔心未來的編碼問題...

+0

我強烈建議使用NSMutableArray類,cards [j] look c-ish。 – 2011-04-19 09:26:00

回答

0

的問題是,

[cardlist substringWithRange:NSMakeRange(i,2)]] 

返回NSString,你沒有自己。由於您不擁有它,因此不能保證該字符串在您的LXPPlayingCard對象的整個生命週期內都有效。如果要保留對該字符串的有效引用,則應修改LXPPlayingCard的聲明,以使cardCV屬性變爲copy屬性,而不是assign。替換:

@property (readwrite, assign) NSString* cardCV; 

有:

@property (readwrite, copy) NSString* cardCV; 

通過這樣做,當你發送-setCardCV:喜歡:

[cards[j] setCardCV:[cardlist substringWithRange:NSMakeRange(i,2)]]; 

setCardCV會複製它的參數,[cardlist substringWithRange:NSMakeRange(i,2)],和你的對象將擁有所有權那個字符串。這意味着字符串將在該對象的整個生命週期內保持有效。請記住,因爲你已經擁有了該字符串的所有權,所以你有責任釋放它。因此,你需要實現一個-dealloc方法:

- (void)dealloc { 
    [cardCV release]; 
    [super dealloc]; 
} 

這意味着相應的LXPPlayingCard被釋放時,存儲在cardCV字符串被釋放了。

+0

Bavarious,非常感謝!現在一切正常。順便說一句,如果我使用簡單的'NSString *'變量,如何成爲字符串形式'[cardlist substringWithRange:NSMakeRange(i,2)]]']的所有者?使用'保留'?我的意思是: NSString * temp; ... temp = [cardlist substringWithRange:NSMakeRange(i,2)]; [temp retain]; 我對不對?我該讀什麼來了解你知道的所有這些事情? :-) – 2011-04-19 12:58:34

+0

@yyk如果它只是一個本地/自動變量,即只用於特定方法的變量,那麼您通常不需要擁有它。這些變量在整個方法中都是有效的。但是,是的,如果您需要獲取該字符串的所有權,請使用'-copy'或'-retain'。您應該閱讀[內存管理編程指南](http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html)以獲取關於內存管理的更詳細討論。 – 2011-04-19 21:57:20

相關問題