使用 ARC 手动保留

Posted

技术标签:

【中文标题】使用 ARC 手动保留【英文标题】:Manual retain with ARC 【发布时间】:2011-12-09 04:59:40 【问题描述】:

在 ARC 之前,我有以下代码在异步操作进行时保留委托:

- (void)startAsyncWork

    [_delegate retain];
    // calls executeAsyncWork asynchronously


- (void)executeAsyncWork

    // when finished, calls stopAsyncWork


- (void)stopAsyncWork

    [_delegate release];

ARC 与此模式的等价物是什么?

【问题讨论】:

【参考方案1】:

我偶尔需要手动保留和释放东西(有时只是为了调试)并想出了以下宏:

#define AntiARCRetain(...) void *retainedThing = (__bridge_retained void *)__VA_ARGS__; retainedThing = retainedThing
#define AntiARCRelease(...) void *retainedThing = (__bridge void *) __VA_ARGS__; id unretainedThing = (__bridge_transfer id)retainedThing; unretainedThing = nil

这是通过使用 __bridge_retained 和 __bridge_transfer 将事物转换为 (void *) 来实现的,这会导致事物被保留,或者在不调用 retain 的情况下创建强引用。

玩得开心,但要小心!

【讨论】:

第一个宏这部分是什么原因:retainedThing = retainedThing? 这是我防止编译器生成有关未使用变量的警告的方法。 谢谢,还是有用的! 这让我喜极而泣。在对 NSInvocations 进行了一些调整和摆弄之后,很明显我的返回值没有被保留足够长的时间来返回给调用者,所以我的一堆 hack 又获得了两个 hack。非常感谢。 这正是我想要的解决方案,但它对我不起作用。我收到“预期表达式”和“使用未声明的标识符“retainedThing”编译器错误。【参考方案2】:

为什么不在异步任务期间将您的委托对象分配给一个强 ivar?

或者在executeAsyncWork中有一个局部变量

- (void)executeAsyncWork

    id localCopy = _delegate;

    if (localCopy != nil) // since this method is async, the delegate might have gone
    
        // do work on local copy
    

【讨论】:

谢谢。这也是我的第一个想法。我希望会有另一个巧妙的技巧;-)。 @hypercrypt:GCD 不是让变量挂起的解决方案,但它是实际执行异步工作的一种特别好的方法。 @hypercrypt:我知道 GCD,但这不是这里的解决方案 ;-)。我正在使用 NSURLConnectionDelegate。【参考方案3】:

类似这样的:

- (void)startAsyncWork

    id<YourProtocol> delegate = _delegate;
    dispatch_async(/* some queue */, ^
        // do work
        [delegate doSomething];
    

该块将根据需要保留委托...

【讨论】:

以上是关于使用 ARC 手动保留的主要内容,如果未能解决你的问题,请参考以下文章

for 循环中的强类对象未保留在 ARC 中

使用ARC为ios声明只读属性的正确方法是啥

iOS开发-33学习手动内存管理临时抛弃ARC以及retain/assign知识——iOSproject师面试必考内容

iOS内存管理-ARC

超越Objective-C,超越Swift

编译器特性ARC