retainCount
是禁忌,不可靠,不可预测的,一般不应使用。我不会在我的代码中的任何地方使用它,但我在一个类中以一种有趣的方式使用它。
我有一个运行一个无限运行的线程的类,直到线程被取消。问题是线程增加了所有者的保留计数,在我的例子中是实例化它的类。所以,即使我已经完成了使用该类,该实例仍然会出现问题,除非管理我的类的人也有智能知道关闭该线程。这是一个解决方案,但这是我在代码中找到的。
- (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];
}
这是一个聪明的解决方案,但我不确定该怎么想。它会覆盖类上的释放并检查保留计数是否为2.换句话说,它检查线程是否是保持对象存活的唯一因素(因为保留计数是关于从2减1到1)如果是,则终止线程(quitDispatchThread
将阻塞直到线程被终止)。
所以......
通常人们会说要清除retainCount
,因为你不知道那里是否有一些自动释放。但是,如果retainCount为1,那么我知道只有线程保持活着的事实我不必担心retainCount可能因某些自动释放等而关闭......
我准备删除它,但它实际上似乎有意义。其他对象不必知道我的类正在运行一个线程。其他对象可以安全retain
和release
甚至autorelease
拥有该线程的对象,而不必担心关闭线程,因为它会自行处理。
这段代码实际上感觉很干净,令我感到惊讶。
我使用NSThread的事实增加了我的对象的保留计数。我的对象是target
,selector
是线程运行的方法。
initWithTarget:选择器:对象
返回使用给定参数初始化的NSThread对象。
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
参数
靶
发送者指定的消息发送到的对象。
选择
要发送给目标的邮件的选择器。这个选择器必须 只取一个参数,但不能有返回值。
参数
传递给目标的单个参数。可能是零。
返回值
使用给定参数初始化的NSThread对象。
讨论
对于非垃圾收集的应用程序,方法选择器是 负责为新分离的设置自动释放池 线程并在它退出之前释放该池。垃圾回收 应用程序不需要创建自动释放池。
在执行分离线程期间保留对象target和argument。它们最终在线程时被释放 退出。
答案 0 :(得分:6)
retainCount
是禁忌,不可靠,不可预测的,一般不应使用。
您可以依赖retainCount
IFF的值,您的对象不会传递任何对您不透明的代码,例如任何Cocoa框架。在实践中,这几乎是不可能实现的,因此是警告。 Cocoa的内部可能会将您的对象传递,保留,释放,并将其多次放入自动释放池中,并且由于多种原因,您无法在任何给定点依赖其绝对值。
问题是线程增加了所有者的保留计数,在我的例子中是实例化它的类。
这是一个保留周期。这里的答案是找到一种方法来打破这个循环,而不是颠覆引用计数机制。当你的线程或拥有对象知道线程正在执行的工作已经完成(或者需要提前停止)时,必须在解除分配之前有一些点。
听起来拥有对象是客户端代码与线程正在进行的工作的接口。这个拥有对象需要一个“立即关闭”方法,需要在其所有者发布之前调用(并记录为“必须被调用”)。在该关闭方法中,您可以通过释放线程来中断循环。
我不确定线程正在保留其创建者的情况(周期是一个非常明确的迹象表明某些你的所有权模式有问题) - 我猜你是'使用NSThread
和initWithTarget:...
,目标是创建/拥有对象。这是标准MVC模式的混合 - 线程的所有者是“控制器”,线程本身(以及它运行的代码)更像是“模型”。
换句话说,控制器不应包含线程的代码。我建议您将线程的代码分解为另一个用作目标的对象。然后控制器对象拥有线程本身和“工作”目标对象,它们都没有拥有控制器。 Voilà,没有循环!
答案 1 :(得分:2)
不。你依赖的是一个抽象的实现,它公开地标记着“Keep Out”的标志。
使用您自己的内存和实现来管理您的依赖项。这可能包括ivar和/或完成/销毁阶段的方法。
另请参阅release
的文档:
<强>释放强>
减少接收者的引用计数。 (所需的)
- (oneway void)release
<强>讨论强>
当引用计数达到0时,会向接收方发送dealloc消息。
您只能实现此方法来定义自己的方法 参考计数方案。这样的实现不应该调用 继承方法;也就是说,它们不应包含发布消息 超级。
如果您想确保您的程序在多个版本中正常运行,最好立即更改。