在ARC中,'[[something retain] autorelease]'的等价语句是什么?

6
在ARC中,等效于[[something retain] autorelease]的是什么?
我有一个问题,即类DBRequest调用我的代理来表示完成。我的代理然后将DBRequest实例设置为nil,从而释放它。但是当堆栈从我的代理弹出并跳回到DBRequest时,它当然会崩溃。
如果我不在ARC中,在我的代理中,我将简单地做[[theDbRequest retain] autorelease]在释放对它的引用之前,这样它就能存活足够长的时间,直到下一个运行循环将其自动释放。
在ARC中我该怎么办?
3个回答

6

你觉得添加一些像这样的东西怎么样

__strong DBRequest * myself = self;
[delegate reportDone];

我认为这将增加self对象直到函数结束,防止它过早失效。

可以打开Dropbox的代码并这样做...但我希望有一种方法可以在不需要修改他们的代码的情况下完成。 - Chris
3
@Chris,好的,我没有意识到他们代码中有那一部分。我不确定,但你可能可以在你的代码中加入__autoreleasing DBRequest * theDBRequest = dbRequest - Winston Ewert
1
最终,那正是我所做的 :) - Chris

3
我的代理然后将DBRequest实例设置为nil,这将释放它。但是当堆栈从我的代理弹出并跳回DBRequest时,它当然会崩溃。
显然,这一直都是一个糟糕的策略,你的[[theDbRequest retain] autorelease]只是掩盖了问题,是吗?
不做任何事情即可。那么你的实例变量就会保留下来; 那又怎样呢?你知道ARC会在你dealloc时为你释放它。
重要的是不要释放theDbRequest,而是将theDbRequest的引用设置为你自己(即代理)的nil,以便在你不存在时不再尝试回调你。你自己的dealloc将是执行此操作的好地方。
希望我正确地理解了问题。如果不是,请发布一些代码!

我认为这是由于涉及的Dropbox API没有使用ARC编写造成的问题,因此ARC无法确定所涉及的所有权。我知道每当您调用可能会释放自己的委托时,最好先调用“self retain autorelease”,但是Dropbox API没有这样做,所以我必须想办法解决。但是怎么办呢? - Chris
这里还有一些有趣的东西,如果我不将theDbRequest设置为nil,它永远不会被释放(即使我的委托被释放)。ARC的工作方式真是神秘?让人想回到非ARC领域…… - Chris
抱歉,我不了解DropBox API。可能存在命名问题吗?当我们从非ARC文件切换到ARC文件时,ARC会根据方法的名称做出管理内存的假设。有一个非常好的WWDC 2011视频来处理这个问题;通过添加告诉ARC该怎么做的限定符,有办法解决它。 - matt
此外,在术语上要小心:released 不等于 dealloced。我保证当您的 delegate 被 dealloced 时,ARC 会释放一个 strong ivar。但如果那不是最后一个引用,它可能不会 dealloc ivar。您可能需要在这里使用弱引用(ARC-weak,非常酷)。但在尝试之前,请使用 Instruments 来确定谁正在保留您的 delegate。并注意保留循环,在 ARC 下很容易出现;请参阅我的书,http://www.apeth.com/iOSBook/ch12.html#_retain_cycles_and_weak_references。 - matt

3
正如@matt所说,如果您什么都不做,当您的对象被销毁时,ARC会自动清理 - 将您创建的DBRequest分配给实例变量即可处理此问题(前提是您的对象比您创建的对象存在时间更长)。
如果您需要在对象死亡之前释放DBRequest,那么您需要一个与[[theDbRequest retain] autorelease]等效的支持ARC的“技巧”。现在,除非您正在构建自己的自动释放池,否则您以前的方法将在当前事件结束时触发。按照这个逻辑尝试:
  1. 向您的类添加一个简单的方法,只需将theDbRequest设置为nil,我们称之为cleanUpTheDbRequest
  2. 将委托回调更改为调用[self performSelectorOnMainThread:@selector(cleanUpTheDbRequest) withObject:nil waitUntilDone:NO],而不是直接将nil分配给theDbRequest
这应该会延迟分配nil,直到当前事件结束,就像您的自动释放“技巧”一样。如果您的DBRequest跨多个事件存在,则先前的方法会在调用autorelease的事件结束时启动,而此方法会在调用委托方法的事件结束时启动。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接