Referring to weak self inside a nested block
It depends.
You only create a retain cycle if you actually store the block (because self
points to the block, and block points to self
). If you don't intend to store either of the blocks, using the strong reference to self
is good enough --- block will be released first after it got executed, and then it will release it's pointer to self
.
In your particular example, unless you're performing more operations which are not shown, you don't need to create any weakerWeakerEvenWeakerSelfs.
Use [weak self] in the nested block in swift
If you don't use [weak self], then for the life time of that block, you can have a circular reference between it and the object self refers to, when an object loses a reference to it, its reference drops by one, when it reaches zero then it is deallocates and reduces the reference count of any object it has a reference to. If you have a circular reference then neither are going to reach zero, because neither is going to get to zero to deallocate itself and reduce the reference to the other. For regular objects this is a problem because they will never be deallocated, for block though, it can depend on how they are used, if they are passed to a function that uses them straight away, then once they are executed they will be deallocated, and any circular references will be cut, it may be even beneficial that whilst your block is executing that it and self can't go away, but if the block is retained as an instance variable to be called, then you have a circular reference that will never go away. The way to deal with is is to use [weak self], saying references to self are weak in this block, you can then just deal with that on each time you use it, self?.myFunction() for example, or you can create a strong reference at the beginning, it used to be you used to have to use a different variable to self, but now you can go
guard let self = self else { return }
one of the good things of doing it this way, you are saying if it gets this far I want the block to execute completely, you have created a circular reference for the execution of the block and it will not go away until the block finishes executing. For example if you have a few functions starting with self?, then mid way through your block executing self could become nil, and only the first few functions are executed and the later are not.
Should I use weakSelf in nested blocks?
In this situation, you are not worried about cyclic references. What you are worried about is a situation where the object self isn't actually needed anymore, but using self inside a nested block would keep it unnecessarily alive. For example, if you have a view controller that should go away when the view is removed by the screen, but you download an image that you would like to display in the controllers view. If the image arrives long after the view is already gone, you don't want the view controller alive anymore.
Best is
__weak typeof (self) weakSelf = self;
before calling the outermost method. Then within every block that ought to use self, you add
typeof (self) strongSelf = weakSelf;
and use strongSelf within that block. Depending on the situation, you might want to check that strongSelf isn't nil at that point, but sending messages to strongSelf when it is nil has no effect, so if all you do is sending messages and getting or setting properties, then a check for nil is not necessary.
What happens if you don't do this? The difference will be that self may be kept alive unnecessarily into the innermost block, if you use self everywhere (or just in the innermost block).
Weak/Strong reference within nested blocks
(@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 byweakSelf
. 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 whateverweakSelf
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, andself
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 methodnetworkCall_2
then as covered above Objective-C will keep a strong reference across the call to any object a method is invoked on, soself
cannot be deallocated during a call. So an active call is never terminated due to itsself
disappearing.If your
networkCall_2
is indeed a property as shown then the object referenced byweakSelf
(theA
above) will not be deallocated across the property call, as in (1). However when then calling thecompletionHandler:
method on whatever object the property call returned (theB
above) thenA
could be deallocated across that call (unless that call holds a strong reference toA
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
break retain cycle in a block nested in another block
I think you can just create new strong reference inside nested block, like this:
- (void)test {
__weak typeof(self) weakSelf = self;
[self.viewSource fetchData:^(BOOL succeed, NSError * _Nonnull error, id _Nonnull data) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.dataSource disposalData:^{
__strong typeof(weakSelf) strongSelf = weakSelf; // <- new strong ref
[strongSelf updateUI];
}];
}];
}
It will override the first strongSelf
in the nested block scope. And it will be only alive during the execution of the nested block without strong reference cycle created. I think so =)
Do we need to repeat `guard let self = self else { return }` inside each nested closure to keep strong self?
Yes, one is enough.
If you write
guard let self = self else { return }
you'll create a new local variable that will hold a strong reference to the outside weak self.
It's the same as writing
guard let strongSelf = self else { return }
and then use strongSelf
for the rest of the block.
When to weak and when to strong reference for nested block in block
You do need a weak reference for the cell completion handler, because you have a reference cycle: self > UITableView > UITableViewCell > self
.
You do not need to use the __strong
qualifier. Variables are strong references by default.
You do not need a weak reference for the animation and transition completion handlers, as those blocks are released as soon as the transition completes, but in this case they can't use self
because they're nested inside of a block that can't capture self
.
So keep weakSelf
and strongSelf
, and use the same strongSelf
variable inside all of the nested blocks.
Swift guarding weak self for nested callbacks
I think most part in @Andriy's answer is correct. But the most correct answer is that we don't even need to put [weak self]
in any nested blocks.
When I first heard this from my colleagues, I don't want to buy it. But the truth is that, the first block defines the captured self
to be weak
and this captured self will be affecting all the captured self within current scope, in other words, within first block's {}
. Therefore, there is no need to apply [weak self]
any more if we have done it in the first most layer of callback.
It is very hard to find the exact document from Apple to prove this but the following code snippet with core foundation retain count CFGetRetainCount()
it can prove that's true.
class TestClass {
var name = ""
var block1: (()->Void)?
var block2: (()->Void)?
func test() {
print(CFGetRetainCount(self))
self.block1 = { [weak self] in
self?.block2 = { // [weak self] in
print(CFGetRetainCount(self))
}
self?.block2?()
print(CFGetRetainCount(self))
}
self.block1?()
print(CFGetRetainCount(self))
}
deinit {
print(CFGetRetainCount(self))
}
}
do {
let tstClass = TestClass()
print(CFGetRetainCount(tstClass))
tstClass.test()
print(CFGetRetainCount(tstClass))
}
If you are interested, you can try this in your playground, feel free to remove the comment for the [weak self]
for block2, you will see the same answer.
Retain count is always 2 and deinit
is called correctly.
Related Topics
How to Draw Radial Gradients in a Calayer
Xcode 4: Build Failed, No Issues
Add Left/Right Horizontal Padding to Uilabel
Automatic Otp Verification in iOS
How to Add Iphonex Launch Image
Broken Uisearchbar Animation Embedded in Navigationitem
"Your Binary Is Not Optimized for iPhone 5" (Itms-90096) When Submitting
Initializer Does Not Override a Designated Initializer from Its Superclass
Determine If iOS Device Is 32- or 64-Bit
How to Do Programmatically Gradient Border Color Uibutton with Swift
How to Combine Two Dictionary Instances in Swift
How to Make a Function Execute Every Second in Swift
Presenting a View Controller Modally from an Action Sheet's Delegate in iOS8 - iOS11
How to Enable Arc Project-Wide in Xcode 4.2
How to Set Cmake_C_Compiler and Cmake_Cxx_Compiler for Building Assimp for iOS
Swiftui Withanimation Completion Callback
How to Prevent from Scrolling Uitableview Up When Nsfetchedresultscontroller Add New Record