在将对象添加到NSMutableArray之后,对象的实例变量中没有值

时间:2010-12-16 06:48:46

标签: objective-c

我正在将一个带有两个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: 

2 个答案:

答案 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属性,则会为您创建这些方法。如果您想了解更多,请查看键值编码。非常奇妙的东西建立在它之上。