Blocks: Release object in completion handler?
在我的applicationDidFinishLaunching:方法中,我创建一个对象并对其调用异步方法,如下所示:
1 2 3 4 5 6 7 8 9
| - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
Foo *foo = [[Foo alloc] init];
[foo asynchronousMethodWithCompletion:^{
// Location A
}];
// Location B
} |
如果我不使用ARC,我应该把[foo release]放在哪里?在完成块内(位置A)还是在异步方法调用后(位置B)?或者根本不重要?
您将[foo release]放在位置B,就像通常在有常规方法调用而不是块的情况下那样。块将保留对象并在完成后释放它。
- 即使该块仅基于堆栈,它也会这样做吗?或者我必须在asynchronousMethodWithCompletion:中执行[block copy]?我把__block放在Foo *foo = [[Foo alloc] init];前面,有关系吗?
- 这是一大堆新问题。在您的示例中,不需要复制块。另外,您不需要使用__block关键字,因为它会阻止foo保留。读取块和变量:developer.apple.com/library/mac/documentation/cocoa/concept‌&8203;ual/…还可以检查stackoverflow.com/questions/7080927/…。如果您还有问题,请打开一次新的。
- @泰姬陵:如果复制,该块将只保留foo。但是,如果块超过调用时间,就保证它被复制。您是否需要在asynchonousMethodWithCompletion:中编写copy,取决于它是如何编写的(您没有向我们显示代码)。您需要在以后存储它之前复制它,例如在实例变量或一般容器中;如果它只是传递给另一个接受块参数的函数,那么不需要复制它,因为如果该函数需要以后存储它,它负责复制它。
- @newacct:我在某个地方读到,当基于堆栈的块超出作用域时,它只会被释放。这不是真的吗?不管怎样,你的评论确实帮助我更好地理解了积木,谢谢!
- @泰姬陵:是的,那是真的
- @纽阿克特:但这是否与你所说的"但如果块超过调用时间,它就一定会被复制"矛盾呢?
- @泰姬陵:不,无论函数或方法将块存储在比调用时间长的地方,都必须存储块的副本。
- 我在理解这一点上仍然有一些问题。在我上面的例子中,asynchronousMethodWithCompletion:将立即返回。因此,当applicationDidFinishLaunching:返回时,块仍将执行,但没有人会引用它。块现在是否已超出范围,导致它立即被释放,即使它当前正在执行,如果没有,那么"块超出范围"的含义是什么?
- @泰姬陵:对象foo可以复制块,完成后释放。如果foo不是你的班,别担心它会照顾好你的。如果您自己编写foo类,那么您可能需要在asynchronousMethodWithCompletion方法中复制给定的块,并在完成后释放它。这将取决于您将如何在类内使用给定的块,正如newacct已经说过的那样。
- foo是我自己的班级。在asynchronousMethodWithCompletion:中,我创建了一个NSURLConnection,将该块赋给一个实例变量(例如,x),并在调用NSURLConnection的委托方法时调用它。所以我必须在开始的时候做x = [block copy];,在结束的时候做[x release];?但这意味着基于堆栈的块不会执行任何操作,例如自动保留它使用的对象,并且一旦复制它,对象就会自动保留,直到我再次释放块?我想我明白了。
- tajmahal @:像我说的,如果asynchronousMethodWithCompletion:stores布拉克(为你的安全,在instance可变),这需要一个大的商店,然后复制的块(为你,与x = [block copy];,你需要释放它,当Foo是xdeallocated或是重新assigned,作为与所有面向对象instance如果,相反,你的variables)asynchronousMethodWithCompletion:简单的歌你喜欢的lls dispatch_async()布拉克和不与它本身的商店,然后它不需要复制它。"的对象是自动释放的块retained直到我再次?"直到布拉克是deallocated
- 我看到的,谢谢!