2011-04-19 61 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

相关问题