我定义了以下变量:

@property (nonatomic, retain) NSMutableArray *arraySpeechSentences;


我正在尝试通过以下方式对其进行初始化:

// Set the array of sentences to the stored array
NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
arraySpeechSentences = speechSentences;
[speechSentences release];


当我尝试调用[arraySpeechSentences count]时,应用程序崩溃了。但是,如果我通过以下方式设置变量:

// Set the array of sentences to the stored array
NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
self.arraySpeechSentences = speechSentences;
[speechSentences release];


我可以称呼[arraySpeechSentences count]非常好。我的印象是,如果你使用自我。它只是检查变量是否已设置,如果已设置,它将在分配新值之前释放该对象。我是否理解错了?如果是,我应该何时使用自我。设置值?

谢谢你的帮助,
艾略特

最佳答案

我将尝试为此提供详细的答案。

首先,当您使用@property/@synthesize指令时,您将围绕变量创建getter和setter方法。

在您的情况下,该变量称为arraySpeechSentences(编译器将为您创建变量),您可以使用self.访问这些方法(setter和getter)。

self.arraySpeechSentences = // something


是相同的

[self setArraySpeechSentences:something]; // setter




NSMutableArray* something = self.arraySpeechSentences;


等于

NSMutableArray* something = [self arraySpeechSentences]; // getter


在第一段代码中

NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
arraySpeechSentences = speechSentences;


arraySpeechSentences指向同一对象speechSentences指向。但是,当您执行[speechSentences release]时,便会释放该对象,而现在arraySpeechSentences是一个悬空的指针。我想您会收到一条发送到已释放实例的消息。尝试使僵尸看到它。

说到保留计数,当您执行alloc-init时,数组的保留计数为1。
但是,当您release使用它时,保留计数将变为零,该对象不再存在,并且尝试访问arraySpeechSentences时会崩溃。

相反,当您处理属性时,应用于变量的策略很重要。由于该属性使用retain策略,因此在设置对象时

self.arraySpeechSentences = // something


被引用对象的保留计数增加。在幕后,说self.arraySpeechSentences = // something等于称呼二传手

- (void)setArraySpeechSentences:(NSMutableArray*)newValue
{
    // pseudo code here...
    if(newValue != arraySpeechSentences) {

       [arraySpeechSentences release];
       arraySpeechSentences = [newValue retain];
    }
}


第二个代码段工作是因为对象的保留计数在执行alloc-init时为1,在调用self.arraySpeechSentences =时变为2,在执行释放时返回为1。这次,由于保留计数为1,因此该对象保持活动状态。

如果您拥有具有retaincopy策略的属性,请不要忘记像dealloc那样释放对象,否则可能会泄漏。

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


为了了解内存的工作原理,我建议阅读MemoryManagement Apple doc

附言从iOS 5开始,有一个称为ARC(自动引用计数)的新编译器功能,可让您忘记retain/release调用。另外,由于它会迫使您根据对象图进行思考,因此建议您进行研究。

希望能有所帮助。

10-08 06:07