我正在为Ojective-C编写一个月的编码并陷入僵局。需要帮忙。 这是故事:
我有一个简单的类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
我也没有更复杂的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类:
@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
和主窗口上的两个按钮,我链接到openNewDeck
和printDeckContent
方法。
问题是应用程序因错误“EXC_BAD_ACCESS”而失败,并且它发生在i
= 3上,因为(当我使用调试器时)[card[i] cardCV]
不是CFString。
我尝试使用不同的字符串来填充套牌,有时程序在显示[cards[i] cardCV]
的第一圈时失败了。
我真的不明白会发生什么,但我想它以某种方式与指针和内存分配规则相关联,因为简单类型的数据(例如position
)没有问题,showList
方法正常工作它从fill
方法调用。
拜托,帮我一把!我疯了!该程序非常简单,我对未来编码中的问题感到非常紧张......
答案 0 :(得分: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
中存储的字符串也会被释放。