手册对象生存与ARC(Manual object lifetime with ARC)

2019-06-24 05:57发布

检查下面的代码,并假设它是根据ARC编译:

- (void)foo {
    NSOperationQueue *oq = [[NSOperationQueue alloc] init];
    [oq addOperationWithBlock:^{
        // Pretend that we have a long-running operation here.
    }];
}

虽然操作队列被声明为一个局部变量,其生命周期将一直连续超越法的范围,因为它已经运行的操作。

这是如何实现的?

更新:

我很欣赏罗布Mayoff的深思熟虑出来的意见,但我想我没有正确地问我的问题。 我不是问NSOperationQueue一个具体的问题,而是关于ARC对象的生命周期一般问题。 具体来说,我的问题是这样的:

怎么样,ARC下,可以将对象参与其自己的生命周期的管理?

我已经很长一段时间的程序员,我很清楚这样的事情的陷阱。 我不是在寻找待讲学,这是否是一个好或坏主意。 我想一般是一个坏的。 相反,我的问题是学术: 无论是好还是坏主意或没有,怎么会在ARC做到这一点,具体是什么语法,这样做呢?

Answer 1:

作为一般情况下,你可以随时给自己参考。 例如:

@implementation MasterOfMyOwnDestiny
{
   MasterOfMyOwnDestiny *alsoMe;
}

- (void) lifeIsGood
{
    alsoMe = self;
}

- (void) woeIsMe
{
    alsoMe = nil;
}

...

@end


Answer 2:

这里有几种可能性:

  1. NSOperationQueue保留了自己,直到它是空的,然后释放本身。

  2. NSOperationQueue导致一些其他物体把它保留下来。 例如,由于NSOperationQueue使用GCD,也许addOperationWithBlock:看起来是这样的:

     - (void)addOperationWithBlock:(void (^)(void))block { void (^wrapperBlock)(void) = ^{ block(); [self executeNextBlock]; }; if (self.isCurrentlyExecuting) { [self.queuedBlocks addObject:wrapperBlock]; } else { self.isCurrentlyExecuting = YES; dispatch_async(self.dispatchQueue, wrapperBlock); } } 

    在该代码中, wrapperBlock包含强参考NSOperationQueue ,所以(假设ARC),它保留了NSOperationQueue 。 (真正的addOperationWithBlock:比这更复杂,因为它是线程安全的,并支持并发执行多个块。)

  3. NSOperationQueue 活过去你的范围foo方法。 也许通过时间addOperationWithBlock:回报,你的长期运行的块已经被提交给GCD队列。 既然你不保持一个强引用oq ,没有理由oq 不应该被释放。



Answer 3:

在该示例代码给予,ARC,所述NSOperationQueue下,作为本地的块的包封词法作用域,被捕获由块捕获。 基本上,块保存,因此它可以从块内后可以访问的指针的值。 实际上,这发生无论你使用ARC与否; 不同的是,ARC下,对象变量自动保持和释放该块被复制和释放。

该段“对象和块变量”在块编程主题指南是这个东西很好的参考。



Answer 4:

我能想到的最简单的事情将有一个全球性的NSMutableArray(或一组,或其他),对象将自身添加到和删除自身。 另一个想法是把(如你已经承认)奇怪的内存管理代码在一个类别在非ARC文件,只是使用-retain和直接-release。



文章来源: Manual object lifetime with ARC