【发布时间】:2012-04-05 16:03:25
【问题描述】:
RetainCount == 坏
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];
}
这是一个聪明的解决方案,但我不知道该怎么想。它覆盖类上的 release 并检查保留计数是否为 2。换句话说,它检查线程是否是唯一使我的对象保持活动状态的东西(因为保留计数约为从 2 减到 1),如果是,则终止线程(quitDispatchThread 将阻塞,直到线程终止)。
所以……
能否依靠retainCount来判断是否为1?
通常人们说要远离retainCount,因为你不知道那里是否有一些自动发布。但是,如果retainCount 是一个,那么我知道只有线程保持它处于活动状态,我不必担心retainCount 可能由于某些自动释放等而关闭......
这段代码有什么问题?
我正要删除它,但它实际上似乎是有道理的。其他对象不必知道我的类正在运行线程。其他对象可以安全地 retain 和 release 甚至 autorelease 拥有线程的对象,而不必担心关闭线程,因为它会自行处理。
这段代码实际上感觉很干净,这让我很惊讶。
编辑 :: NSThread 正在保留我的对象
我使用 NSThread 的事实增加了我的对象的保留计数。我的对象是target,selector 是线程运行的方法。
initWithTarget:selector:object:
返回一个使用给定参数初始化的 NSThread 对象。
- (id)initWithTarget:(id)目标选择器:(SEL)选择器对象:(id)参数
参数
目标
选择器指定的消息要发送到的对象。
选择器
要发送到目标的消息的选择器。这个选择器必须 只接受一个参数,并且不能有返回值。
参数
传递给目标的单个参数。可能为零。
返回值
使用给定参数初始化的 NSThread 对象。
讨论
对于非垃圾收集的应用程序,方法选择器是 负责为新分离的建立一个自动释放池 线程并在它退出之前释放该池。垃圾收集 应用程序不需要创建自动释放池。
对象目标和参数在分离线程执行期间保留。它们在线程最终释放时 退出。
【问题讨论】:
-
(舌尖上)如果你觉得这段代码很干净,试着把它移植到 ARC。
-
试图通过操纵retainCount 来修复Cocoa 中的任何问题是一个存在设计问题的信号。我认为循环所有权是问题的根源。你能重新设计你的代码,使线程没有对拥有对象的保留引用吗?这段代码看起来很干净,就像打蜡的胡子看起来很干净一样,但是这段代码看起来不合适,就像奶奶嘴唇上的蜡胡子不合适一样。
-
@Mr.Berna 我希望奶奶没有小胡子,但如果她有,我希望它会打蜡。 :D 我正在使用
NSThread,当您将它初始化到目标、选择器、参数时,它会保留target。所以......我认为我无法绕过循环所有权。但是,该对象(及其关联的线程)仅在一处被清理,因为它仅在代码中的一处使用。我已经有代码可以做到这一点。我什至正要检查零钱。然而,当我回顾这个变化时,我不得不问自己为什么要这样做,尤其是当我知道它有效时。 -
我的答案已更新;最后两段说明您对
-[NSThread initWithTarget:selector:object:]的使用。简而言之,让目标不是线程的所有者。
标签: objective-c ios nsthread retaincount