What is difference between [self] in & [weak self] in in Swift?
Writing [self]
is same as leaving the closure as it is meaning it could cause retain cycle unlike [weak self]
, BTW no need for any of them with DispatchQueue.main.async {
as GCD queues don't hold a strong reference to self
When to use [self] vs [weak self] in swift blocks?
[self]
indicates that self
is intentionally held with a strong reference (and so some syntax is simplified). [weak self]
indicates that self
is held with a weak reference.
why would I use strong capture
[self]
inside block as there are chances of memory leak
You would use this when you know there is no reference cycle, or when you wish there to be a temporary reference cycle. Capturing self
does not by itself create a cycle. There has to be a cycle. You may know from your code that there isn't. For example, the thing holding the closure may be held by some other object (rather than self
). Good composition (and decomposition of complex types into smaller types) can easily lead to this.
Alternately, you may want a temporary cycle. The most common case of this URLSessionTask. The docs are very valuable here (emphasis added):
After you create a task, you start it by calling its resume() method. The session then maintains a strong reference to the task until the request finishes or fails; you don’t need to maintain a reference to the task unless it’s useful for your app’s internal bookkeeping.
Another common example is DispatchQueue, which similarly holds onto a closure until it finishes. At that point, it releases it, killing the cycle and allowing everything to deallocate. This is useful and powerful (and common!), when used with intent. It's a source of bugs when used accidentally. So Swift requires you to state your intentions and tries to make the situation explicit.
When you build your own types that retain completion handlers, you should strongly consider this pattern, too. After calling the completion handler, set it to nil
(or {_ in }
for non-optionals) to release anything that completion handler might be referencing.
One frustrating effect of the current situation is that developers slap [weak self]
onto closures without thought. That is the opposite of what was intended. Seeing self
was supposed to cause developers to pause and think about the reference graph. I'm not certain it ever really achieved this, but as a Swift programmer you should understand that this is the intent. It's not just random syntax.
Is it the right way using `[weak self]` in swift closure?
Your pattern has race condition. If self
was deallocated at the exact same time as your completion handler closure was executing, it could crash. As a general rule, avoid using the !
forced unwrapping operator if you can.
I’d lean towards the
guard
“early exit” pattern (reducing nested braces, making code easier to read). The standard Swift 4.2 solution is:someTask { [weak self] result in
guard let self = self else { return }
self.xxx = yyy
self.doLongTermWork()
self.finish()
}Before Swift 4.2, which implemented SE-0079, we would have to do something like:
someTask { [weak self] result in
guard let strongSelf = self else { return }
strongSelf.xxx = yyy
strongSelf.doLongTermWork()
strongSelf.finish()
}You can see why we prefer the Swift 4.2 improvement, as this
strongSelf
syntax is inelegant.The other obvious alternative is just:
someTask { [weak self] result in
self?.xxx = yyy
self?.doLongTermWork()
self?.finish()
}Sometimes you need the “weak self - strong self dance” (the first two alternatives), but it would not appear to be the case here. This is likely sufficient.
There are other scenarios/edge cases that one might contemplate, but these are the basic approaches.
Weak self vs self when using closure defined in swift in objective c
First of all try to understand what is a retaincycle
and how it will affect your application..
A retain cycle
is a condition that happens when two objects keeps strong reference to each others.
In such cases these objects won't get deallocated and it will stay in memory forever and leads to memory leak.
Retain cycle in blocks and why should we use weakself
Closures and blocks are independent memory objects and they will retain the objects they reference so if we are accessing any class variable or method inside the closure or block using self
then there is a chance for retain cycle
self.myBlock = ^{ self.someProperty = xyz; };
// RETAIN CYCLE
will get this warning
Capturing 'self' strongly in this block is likely to lead to a retain
cycle
To avoid such situation we should weakSelf to access members
__weak typeof(self) weakSelf = self;
`self.myBlock = ^{ weakSelf.someProperty = xyz; };`
So there is a rule like always use weakSelf in blocks
but there are some special cases like animation blocks
[UIView animateWithDuration:duration animations:^{ [self.superview layoutIfNeeded]; }];
Here we can use self inside the block because the blocks get destroyed automatically once animation completed.
Should I use [weak self] if I don't actually reference self in my completion block?
Capturing the variables, happens only when you use it internally, a closure will NEVER capture the variables by default (not like Java inner class which ALWAYS captures this
), so, it you use a variable (including self
) inside the closure, it is captured.
Also you can manually capture the variables using the [weak self]
, [weak your_variable_here]
, [unowned self]
, [unowned your_variable_here]
, [self]
or [your_variable_here]
If the compiler tells you variable "self" is written to but never read from
, it means that you didn't use self
inside, so it is completely safe not to use [weak self]
, because self
will NOT be captured, because it is not used.
weak self
or unowned self
is needed only when your closure captures self
, and escapes the function it is passed to, especially if it is saved in a variable.
Refer to Closures in Apple's Official Swift Documentation
Difference between weak self vs weak self()
You do not pass [weak self] ()
as an argument to a closure.
[weak self]
is a capture list and precedes the- parameter list/return type declaration
() -> Void
in the closure expression.
The return type or both parameter list and return type can be omitted if they can
be inferred from the context, so all these are valid
and fully equivalent:
dispatch_async(dispatch_get_main_queue()) { [weak self] () -> Void in
self?.doSomething()
}
dispatch_async(dispatch_get_main_queue()) { [weak self] () in
self?.doSomething()
}
dispatch_async(dispatch_get_main_queue()) { [weak self] in
self?.doSomething()
}
The closure takes an empty parameter list ()
and has a Void
return type.
Shall we always use [unowned self] inside closure in Swift
No, there are definitely times where you would not want to use [unowned self]
. Sometimes you want the closure to capture self in order to make sure that it is still around by the time the closure is called.
Example: Making an asynchronous network request
If you are making an asynchronous network request you do want the closure to retain self
for when the request finishes. That object may have otherwise been deallocated but you still want to be able to handle the request finishing.
When to use unowned self
or weak self
The only time where you really want to use [unowned self]
or [weak self]
is when you would create a strong reference cycle. A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around.
In the specific case of a closure, you just need to realize that any variable that is referenced inside of it, gets "owned" by the closure. As long as the closure is around, those objects are guaranteed to be around. The only way to stop that ownership, is to do the [unowned self]
or [weak self]
. So if a class owns a closure, and that closure captures a strong reference to that class, then you have a strong reference cycle between the closure and the class. This also includes if the class owns something that owns the closure.
Specifically in the example from the video
In the example on the slide, TempNotifier
owns the closure through the onChange
member variable. If they did not declare self
as unowned
, the closure would also own self
creating a strong reference cycle.
Difference between unowned
and weak
The difference between unowned
and weak
is that weak
is declared as an Optional while unowned
is not. By declaring it weak
you get to handle the case that it might be nil inside the closure at some point. If you try to access an unowned
variable that happens to be nil, it will crash the whole program. So only use unowned
when you are positive that variable will always be around while the closure is around
In Swift, if I have a closure capturing [weak self], is it good practice to unwrap the optional self at the beginning of the closure?
I believe that the first implementation is better because self could become nil between the statements
And that's why the second implementation is in fact better! If self
is not nil at the first statement, the first statement makes it so that self
couldn't become nil
between the statements. It retains self
exactly for the remainder of the block. This is called "the weak–strong dance".
guard let self = self else { return }
// ^^^^ this self is _strong_, not weak; it retains self
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.
Related Topics
Retrieve String Value from Function with Closure in Swift
Swift: Optional Text in Optional Value
How Replace Position++ Code to Make It Swift 3 Compatible
What Are 'Get' and 'Set' in Swift
Convert a Custom Object to Data to Be Saved in Nsuserdefauts
Uicollectionviewlayout Not Working with Uiimage in Swift 5 and Xcode 11
Why Can't the Swift Compiler Infer This Closure's Type
How to Validate Dynamically Added Textfields on a Button Click in Swiftui
How to Use Keywords as Parameter Names in Swift
Coreplot with Swift: There Is No Yaxis.Majorintervallength
Swift 4.0 Mapview Running Slow
Swiftui Exporting or Sharing Files
How to Line Break Long Large Title in iOS 11