(@trungduc was close to an answer but unfortunately has decided to delete it. So now as I may have inadvertently helped lose you your only answer to date I'll see if I can help you out.)
This answer only applies when using ARC
What are the difference between:
The probably surprising answer is that in this particular example not a lot...
When Objective-C makes a method call on an object it ensures that the object is alive across the call. So in the call:
[weakSelf.networkCall_2 completionHandler:^(id response2) {...}];
which is shorthand (using dot notation) for:
[[weakSelf networkCall_2] completionHandler:^(id response2) {...}];
First weakSelf
is loaded and a strong reference held to the result, call this reference A
. Then the property (method) networkCall_2
is called on A
and a strong reference held to its result, call this B
. At this point the compiler is free to drop the strong reference A
as it is not used passed this point. Finally the call to the method completionHandler:
on B
is called. After that returns, which may be before the passed completion block has been invoked, the compiler is free to drop the strong reference B
.
If A
or B
is nil
above then the calls on them simply return nil
and nothing much happens.
Note: your code is a little unusual, more common might be something like:
[weakSelf networkCall_2:<some argument> completionHandler:^(id response2) {...}];
that is networkCall_2:completionHandler:
is a method on the object referenced by weakSelf
. If this is what your actual code looks like then the above still applies and the compiler will hold a strong reference across the call to whatever weakSelf
references.
Turning now to:
__typeof__(self) strongSelf = weakSelf;
if(response) {
[strongSelf.networkCall_2 completionHandler:^(id response2) {...}];
The compiler first loads weakSelf
and holds a strong reference to it in strongSelf
. Then the property (method) networkCall_2
is called on strongSelf
and a strong reference held to its result, call this B
. At this point the compiler is free to drop the strong reference strongSelf
as it is not used passed this point. Etc.
(Note: "free to drop" in both cases above does not mean the compiler will immediately drop it, it may defer that until the end of the if
or block.)
Notice the similarity in the two descriptions? In this particular example there is really no difference between using weakSelf
and strongSelf
. So why does some code use the strongSelf
pattern? Consider:
__typeof__(self) strongSelf = weakSelf;
if (strongSelf) // object still exists)
{
// *all* three methods will be called
[strongSelf method1];
[strongSelf method2];
[strongSelf method3];
}
vs:
[weakSelf method1]; // call method1 if weakSelf is not nil
[weakSelf method2]; // call method2 if weakSelf is *still* not nil
[weakSelf method3]; // call method3 if weakSelf is *still* not nil
Using the strongSelf
pattern above ensures that either 0 (if weakSelf
is nil
) or 3 method calls are made. If the weakSelf
pattern is used 0, 1, 2 or 3 methods may be called.
Your particular example has the same result either way as there is only one use of strongSelf
/weakSelf
, in the above the result can differ as there are multiple uses of strongSelf
/weakSelf
.
Which leaves us with your question:
Also, what happens if networkCall_2
is running, and self
gets deallocated? Does it finish or terminate the call?
This question reads as though networkCall_2
is a method not a property, see the note above, we'll cover both cases:
If here you are referring to the self
of the method networkCall_2
then as covered above Objective-C will keep a strong reference across the call to any object a method is invoked on, so self
cannot be deallocated during a call. So an active call is never terminated due to its self
disappearing.
If your networkCall_2
is indeed a property as shown then the object referenced by weakSelf
(the A
above) will not be deallocated across the property call, as in (1). However when then calling the completionHandler:
method on whatever object the property call returned (the B
above) then A
could be deallocated across that call (unless that call holds a strong reference to A
by other means).
Hope I understood your question correctly and if so I think your answer boils down to knowing:
An object on which a method (or property) is called will not be deallocated during that method (or property) call.
HTH