问题
Let's assume I have the following typedef:
typedef void (^myBlock)(id);
And I have some method myMethod accepting myBlock as an argument and yielding some id variable to it:
void myMethod(id myObj, myBlock block) {
// ...
block(myObj);
// ...
}
So if I have the following:
- (void) someMethod {
__block id myObj; // Some initialization local to the scope of someMethod;
// myObj = ... some assignment to myObj so it is not nil...
dispatch_async(someQueue(), ^{
// (*) Some long, possibly multi-queued and multi-blocked, processing,
// so we are sure that someMethod will run out:
// ...
// 1. Can I be sure that myObj is still alive and actual here
// after the long processing (*)?
myMethod(myObj, ^(id myObj) {
// (**) Some long, possibly multi-queued, processing here too...
// 2. Can I be sure that myObj is still alive and actual here
// after the long processing (**) finishes?
})
})
}
do I have to specially retain myObj so it would live across different queues/blocks?
Sorry if I'm asking something obvious and enough documented - I've just started learning Objective-C in the time, when ARC is likely a default so it does not require me to care much about these retain counts, autoreleases and other stuff, and think about them only in the situations like I described here.
回答1:
- Can I be sure that myObj is still alive and actual here after the long processing (*)?
Yes, and even if you weren't using the block specifier because the block inside the block retains it.
- Can I be sure that myObj is still alive and actual here after the long processing (**) finishes?
Yes.Every variable used inside a block is retained by ARC.
PS: All this with ARC.
回答2:
- Can I be sure that myObj is still alive and actual here after the long processing (*)?
Yes. Normally, free variables in a block are retained by the block when it is copied. However, this is a __block
variable. In ARC, __block
variables are also retained by the block (however, that is not the case in MRC).
- Can I be sure that myObj is still alive and actual here after the long processing (**) finishes?
This question isn't related to blocks capturing variables at all. Here, myObj
is a parameter, i.e. a local variable, not captured from the surrounding scope. So the question really is, does the argument point to a valid object when the block is called? Since myMethod()
simply synchronously calls its block
argument with the myObj
argument that it gets, under ARC, nothing should go wrong assuming that the arguments were valid when myMethod
was called (i.e. in the outer block). This is true since we agreed that myObj
was valid there from (1) above.
来源:https://stackoverflow.com/questions/13901447/does-a-passing-of-an-object-to-a-block-guarantee-that-its-lifecycle-will-be-reta