我正在将一个带有两个NSString实例变量的对象添加到NSMutableArray中。日志语句告诉我vars设置正确,但在我将它们添加到数组后,它们似乎被覆盖或稍后,根本不显示。这让我疯了。我怀疑它是一个内存管理问题......
很抱歉输出很长,但我很绝望......
当我单击一个按钮并从文本视图中获取文本时,我调用此方法,然后从菜单项调用另一个方法,并且我有日志语句来迭代数组以检查实例变量的值(问题,回答)并且在数组中保存的每个Flashcard对象中都是空白的......
- (IBAction)nextCard:(id)sender
{
int i = 0;
NSLog(@"> Clicked \"Next Card\" button");
NSLog(@"Called method: -(IBAction)nextCard:");
NSString *questionString = [[questionView textStorage] string];
NSString *answerString = [[answerView textStorage] string];
/* Make sure we get input in both fields, otherwise do nothing */
/* Todo: use a regexp lib to make this more robust */
NSString *questionWithoutWhitespace = [questionString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *answerWithoutWhitespace = [answerString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSLog(@" questionString: %@", questionString);
NSLog(@" answerString: %@", answerString);
if ( ([questionWithoutWhitespace length] != 0) && ([answerWithoutWhitespace length] != 0) )
{
Flashcard *flashcard = [Flashcard newCardWithQuestion:questionString andAnswer:answerString];
NSLog(@" Flashcard->question: %@", [flashcard getQuestion]);
NSLog(@" Flashcard->answer: %@", [flashcard getAnswer]);
[cardList addObject:flashcard];
NSLog (@" [cardList count]: %d", [cardList count]);
NSLog(@" FlashCard %i, question: %@", i, [[cardList objectAtIndex:i] getQuestion]);
NSLog(@" FlashCard %i, answer: %@", i, [[cardList objectAtIndex:i] getAnswer]);
i++;
[self clearCard];
}
}
以下是我几次调用之后的输出:
[Session started at 2010-12-15 22:27:21 -0800.]
Called -(void)awakeFromNib
> Clicked "Next Card" button
Called method: -(IBAction)nextCard:
questionString: q1
answerString: a1
Flashcard->question: q1
Flashcard->answer: a1
[cardList count]: 1
FlashCard 0, question: q1
FlashCard 0, answer: a1
Called Method: -(void)clearCard
> Clicked "Next Card" button
Called method: -(IBAction)nextCard:
questionString: q2
answerString: a2
Flashcard->question: q2
Flashcard->answer: a2
[cardList count]: 2
FlashCard 0, question: q2
FlashCard 0, answer: a2
Called Method: -(void)clearCard
> Selected "File -> New" menu option
Called method: -(IBAction)newCardSet:
cardList:
[cardList count]: 2
Element 0 = <Flashcard: 0x480570>
FlashCard 0, question:
FlashCard 0, answer:
Element 1 = <Flashcard: 0x473b70>
FlashCard 1, question:
FlashCard 1, answer:
答案 0 :(得分:1)
问题在于以下两行:
NSString *questionString = [[questionView textStorage] string];
NSString *answerString = [[answerView textStorage] string];
string
方法来自NSAttributedString。文档说这个:
出于性能原因,此方法返回属性字符串对象的当前后备存储。如果要在操作返回的字符串时维护此快照,则应复制相应的子字符串。
所以你需要用以下代码替换这两行:
NSString *questionString = [[[[questionView textStorage] string] copy] autorelease];
NSString *answerString = [[[[answerView textStorage] string] copy] autorelease];
这是因为NSTextStorage是ann NSMutableAttributedString,当它被设置为空白时,您收到的字符串将被清空。
不相关,但您可能希望将i
设置为[cardList count]
,而不是0
。
此外,以new
开头的方法应根据memory management rules返回您拥有的对象。如果newCardWithQuestion:andAnswer:
符合规则,则代码会泄露。如果没有,您应该重命名该方法,可能是删除单词“new”。
答案 1 :(得分:0)
我的猜测完全基于您在此处显示的内容:当您在此处创建retain
对象时,这两个字符串不是copy
'或FlashCard
d:
Flashcard *flashcard = [Flashcard newCardWithQuestion:questionString andAnswer:answerString];
这种方法是什么样的?在该方法的某个时刻,如果这两个字符串是实例变量,则应将它们保留或复制到flashcard
的实例。
此外,这与您的问题无关,但在处理Cocoa时,您倾向于将附件方法命名为- (void)key
,而不是- (void)getKey
,其中key
通常是您的实例变量名。
不仅是这个约定,而且它还允许您使用Runtime执行非常有用的操作,如果使用Declared属性,则会为您创建这些方法。如果您想了解更多,请查看键值编码。非常奇妙的东西建立在它之上。