我正在研究Aaron Hillegass的书,特别是彩票的例子。我对-setEntryDate:
方法有疑问;为什么我要保留date
?该程序仍然有效,但不保留它。
-(void)setEntryDate:(NSCalendarDate *)date {
[date retain];
[entryDate release];
entryDate = date;
}
但这仍然可行:
-(void)setEntryDate:(NSCalendarDate *)date {
entryDate = date;
}
那么为什么我必须保留date
然后释放entryDate
呢?
答案 0 :(得分:7)
它现在有效,但是如果你正在编写一个更大的程序,那么在将来某个不确定的点上,对象date
指向的对象可能被称为setEntryDate
的任何人释放。如果发生这种情况,它将在整个程序的其余部分失效。您将在类中保留此对象,因为该类现在拥有对该对象的引用,并需要指明该对象。通过这样做,即使任何名为setEntryDate
的类要释放date
,您的类仍将保持对它的有效引用。此外,这不仅仅是您正在编写的常规旧方法。这是一个setter,它负责在它所属的类上设置一个实例变量。如果您正在编写非setter方法,则可能不必保留参数。我想说的是保留方法参数并不总是必要的;它只是在这种情况下(几乎所有的setter都处理非原始类型)。
这称为“引用计数”,并详细解释here。现在,既然你刚开始学习,不要担心阅读。当您开始使用内存管理进入更复杂的场景时,该指南是非常有价值的阅读材料。
答案 1 :(得分:3)
因为您声明对象的所有权,retain
就是这样做的。不正确的代码有时会发生正常工作,但这基本上只是运气。
答案 2 :(得分:1)
这些方法称为访问器方法。顾名思义,它们允许检索和设置变量 - 具体来说,它们被称为“getters”和“setter”。
约定(然而,您将在本书的后续章节中看到的不仅仅是约定)是为变量调用“getter”,例如,NSString
称为foo
- (NSString*)foo;
和“二传手”:
- (void)setFoo:(NSString*)newFoo;
在上面的示例中,实现该方法以设置新的日期值。内存管理在第4章中描述,但简而言之,Objective-C对象的工作方式是它们具有“保留计数” - 这表示对象具有的引用数量;在分配时,对象的保留计数为1.然后可以向对象发送retain
或release
消息,以分别增加或减少保留计数。 retain
消息意味着发送消息的对象想要使用该对象,因此retain
是它。 release
消息意味着发送消息的对象不再想要使用该对象,因此减少了保留计数。当对象的保留计数达到0时,将释放该对象。这样就避免了内存泄漏。
保留date
并释放entryDate
的原因是date
是您想要“了解”的新对象;因此,您retain
要求对其拥有所有权。 entryDate
变量指向当前日期对象,但由于您将其设置为新值,因此您不再需要了解它;因此你release
;这可以防止内存泄漏,因为您最初会保留此变量。
正如我之前所说,一旦阅读第4章:内存管理,这个概念就会变得更加清晰。现在,只要接受它,并在解释它时理解其背后的原因。
答案 3 :(得分:1)
如果你通过视频更好地学习,斯坦福大学有published一些关于iPhone开发的视频,这些视频在某种程度上也涵盖了Cocoa和Objective C.查看讲座3,它通过示例和讨论对内存管理进行了很好的概述。