RetainCount确定在这种情况下使用?

保留计数== BAD

retainCount是禁忌,不可靠,不可预知的,一般不应该使用。 我不会在代码中的任何地方使用它,但是我以一种有趣的方式在一个类中看到了它。

我有一个类运行一个线程,无限期地运行,直到线程被取消。 问题是线程增加了所有者的保留计数,在我的例子中是实例化它的类。 所以,即使我已经完成了这个课程,那么这个例子还是会继续存在下去,除非pipe理我的课程的人也知道closures这个线程。 这是一个解决scheme,但这是我在代码中find的。

 - (oneway void)release { // This override allows allows this object to be dealloced // by shutting down the thread when the thread holds the last reference. // Otherwise, the object will never be dealloc'd if (self.retainCount == 2) { [self quitDispatchThread]; } [super release]; } 

这是一个聪明的解决scheme,但我不知道该怎么想。 它覆盖了类的释放,并检查保留计数是否为2.换句话说, 它检查线程是否是保持我的对象唯一的活动 (因为保留计数将从2递减到1 ),如果是,它终止线程( quitDispatchThread将阻塞,直到线程被终止)。

所以…

你可以依靠retainCount看看是否是一个?

通常人们会说要保持清楚的retainCount因为你不知道在那里是否有一些autoreleases。 但是,如果retainCount是一个,那么我知道一个事实,只有线程保持活着,我不必担心retainCount可能会由于某些autoreleases等closures…

这个代码有什么问题?

我正要移除它,但实际上似乎是有道理的。 其他对象不必知道我的类正在运行一个线程。 其他对象可以安全地retainrelease ,甚至可以autorelease拥有该线程的对象,而不必担心由于自己处理而closures线程。

这个代码实际上感觉干净,这让我感到惊讶。

编辑:: NSThread是保留我的对象

我使用NSThread的事实增加了我的对象的保留数。 我的对象是targetselector是线程运行的方法。

initWithTarget:select器:对象:

返回使用给定参数初始化的NSThread对象。

  • (id)initWithTarget:(id)目标select器:(SEL)select器对象:(id)参数

参数

目标

发送由select器指定的消息的对象。

select

消息发送到目标的select器。 这个select器必须只有一个参数,并且不能有返回值。

论据

传递给目标的单个参数。 可能是零。

返回值

用给定参数初始化的NSThread对象。

讨论

对于非垃圾回收的应用程序,方法select器负责为新分离的线程设置一个自动释放池,并在该池退出前释放该池。 垃圾收集的应用程序不需要创build一个自动释放池。

对象的目标和参数在执行分离的线程的过程中保留 。 当线程最终退出时它们被释放。

retainCount是禁忌,不可靠,不可预知的,一般不应该使用。

您可以依赖retainCount IFF的值,您的对象不会通过任何对您而言不透明的代码,例如任何Cocoa框架。 在实践中,这几乎是不可能实现的,因此是警示。 cocoa的内部可能会传递你的对象,保留,释放,并把它放入autorelease池多次,原因很多,你不能依靠它的绝对值在任何给定的点。

问题是线程增加了所有者的保留计数,在我的例子中是实例化它的类。

这是一个保留周期。 这里的答案是find一个打破这个循环的方法,而不是颠覆引用计数机制。 当你的线程或者拥有的对象知道线程正在执行的工作已经完成(或者需要提前停止)的时候, 释放之前必须要有一点。

这听起来像拥有的对象是客户端代码的接口,线程正在做的工作。 这个拥有的对象需要一个“现在closures”的方法,在所有者释放它之前需要被调用(并logging为“必须被调用”)。 在该closures方法中,您可以通过释放线程来中断循环。

我不是很确定线程是保留它的创build者(周期是一个非常清楚的迹象表明,你的所有权模型有问题)发生了什么 – 我猜你正在使用NSThreadinitWithTarget:...目标是创造/拥有的对象。 这是标准MVC模式的一个混合 – 线程的所有者是一个“控制器”,线程本身(和它运行的代码)更多的是一个“模型”。

换句话说,控制器不应该包含线程的代码。 我build议你把线程的代码分解成另一个对象作为目标。 然后控制器对象拥有线程本身和“工作”目标对象,两者都不拥有控制器。 Voilà,没有周期!

不。 你依靠的是一个抽象的实现,公开承载着“保持”的标志。

只需使用自己的内存和实现来pipe理你的依赖关系。 这可能包括ivar和/或完成/销毁阶段的方法。

另请参阅release文档:

发布

减less接收机的参考计数。 (需要)

- (oneway void)release

讨论

当接收器的引用计数达到0时,发送一个dealloc消息。

你只会实现这个方法来定义你自己的引用计数scheme。 这样的实现不应该调用inheritance的方法; 也就是说,他们不应该包含发布消息给super。

如果您想确保您的程序在多个版本中正确运行,最好现在就更改它。