【问题标题】:What's the equivalent of '[[something retain] autorelease]' in ARC?ARC中'[[something retain] autorelease]'的等价物是什么?
【发布时间】:2012-03-10 03:50:37
【问题描述】:

ARC 中 [[something retain] autorelease] 的等价物是什么?

我有一个问题,一个类 DBRequest 调用我的委托来表示完成。然后我的委托将 DBRequest 实例设置为 nil,这就是它的 dealloc。但是当堆栈从我的委托中弹出并跳回 DBRequest 时,它当然会崩溃。

如果我不在 ARC 中,在我的委托中,我只需在释放我对它的引用之前执行 [[theDbRequest retain] autorelease],这样它就可以存活足够长的时间,直到下一个运行循环自动释放它。

我应该在 ARC 中做什么?

【问题讨论】:

    标签: iphone objective-c ios automatic-ref-counting


    【解决方案1】:

    添加类似的东西怎么样

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

    我认为这会增加 self 对象直到函数结束,防止它过早死亡。

    【讨论】:

    • 可以打开保管箱代码并执行此操作...我希望有一种方法可以做到这一点,而无需修改他们的代码。跨度>
    • @Chris,好吧,我没有意识到他们的代码中有这一点。我不确定,但您可以在代码中添加 __autoreleasing DBRequest * theDBRequest = dbRequest
    • 最后,这正是我所做的:)
    【解决方案2】:

    然后我的委托将 DBRequest 实例设置为 nil,这就是它的 dealloc。但是当堆栈从我的委托中弹出并跳回 DBRequest 时,它当然会崩溃。

    当然,这总是一个糟糕的策略,而你的 [[theDbRequest retain] autorelease] 总是在掩盖问题,是吗?

    什么都不做。所以你的实例变量会一直存在;所以呢?您知道 ARC 会在您解除分配时为您释放它。

    重要的是不要释放theDbRequest,而是将DbRequest对(委托)的引用设置为nil,这样它就不会在你不再存在时尝试回调你.您自己的 dealloc 将是执行此操作的好地方。

    希望我正确理解了这个问题。如果没有,请发布一些代码!

    【讨论】:

    • 我认为这是由相关的保管箱 api 引起的问题不是使用 ARC 编写的,因此 arc 不知何故无法确定相关的所有权。我知道,每当您调用可能释放自己的代表时,最好先调用“自我保留自动释放”,但 Dropbox api 并没有这样做,所以我必须做点什么。但是什么?
    • 这里也有一些有趣的事情,如果我不将 theDbRequest 设置为 nil,它就永远不会被释放(即使在我的委托被释放之后)。 ARC以神秘的方式运作?很想跑回非弧地……
    • 抱歉,我不知道 DropBox API。会不会有命名问题?当我们从非 ARC 文件跨越到 ARC 文件时,ARC 会根据方法的 name 对如何管理内存做出假设。有一个非常好的 WWDC 2011 视频可以解决这个问题;有一些方法可以通过添加一个告诉 ARC 做什么的限定符来解决它。
    • 另外,请注意您的术语:released 与 dealloced 不同。我保证当您的委托被解除分配时,ARC 会释放一个强大的 ivar。但如果这不是最后一个引用,那可能不会释放 ivar。您可能需要在这里使用弱引用(ARC-weak,非常酷)。但在您尝试之前,请使用 Instruments 来确定谁保留了您的代表。并注意保留周期,这在 ARC 下很容易出现;看我的书,apeth.com/iOSBook/ch12.html#_retain_cycles_and_weak_references
    【解决方案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 的事件结束时启动,此方法在调用委托方法的事件结束时启动。

    【讨论】:

      猜你喜欢
      • 2012-11-29
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      • 2014-06-12
      • 1970-01-01
      • 2022-11-28
      • 2021-06-19
      • 2012-07-20
      相关资源
      最近更新 更多