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.
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.
Weird weak self and retain cycle behaviour
First of all, all printers are creating and retaining their own Delayer. The delayer takes a closure and, in turn, retains that closure.
Let's try to walk through them one by one.
Printer1
As you stated yourself, it's pretty clear why it's creating a retain cycle. You are passing the self.action
instance method as the closure to the Delayer, and since all closures are reference types, passing self.action
will retain its surrounding scope (which is Printer1).
Printer2
Again, pretty obvious here. You're explicitly capturing a weak reference to self inside the closure you're passing to Delayer, hence not creating a retain cycle.
Printer3
Here, a retain cycle is not created, because the self.weakAction
property is called immediately, and its result (a closure which holds a weak reference to self) is passed on to Delayer. This, in effect, is the exact same thing as what's happening in Printer2
.
Printer4
First, you're capturing a weak reference to self, and then fetching welf?.action
and passing the result into Delayer. Again, welf?.action
is called immediately, and the result (a pointer to an instance method) is passed on to Delayer. The weak reference to self is only kept for the duration of the surrounding scope (the lazy var creation scope), and passing the action
instance method will retain self. This is identical to Printer1
.
Printer5
Here, you're first creating a weak reference to self, and then you're capturing that weak reference inside a new closure that is passed to Delayer. Since self
is never directly referenced in the passed closure, it will not capture self
in that scope, only the welf
weak reference. This is pretty much identical to Printer2
, but with a slightly different syntax.
Personally, I would opt for the Printer2
way (creating a new closure, retaining a weak reference to self and using that to call self?.action
). It makes for the easiest code to follow (as opposed to retaining a variable with a closure that weakly captures self). But, depending on what you're actual use case is, it might of course make sense.
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
with or without [weak self]
The issue is that you’ve made customNetworker
, the CustomNetworker
, a local variable and you lose your strong reference to it as soon as this local variable falls out of scope. When the dataRequest(input:)
method uses a [weak self]
reference, it’s saying that you don’t want dataRequest(input:)
to keep a strong reference to this CustomNetworker
instance, either. As a result, with no strong references, the CustomNetworker
will be deallocated.
You have a few alternatives:
If you remove the
[weak self]
reference in the closure insidedataRequest(input:)
, then it will retain theCustomNetworker
until the closure runs. As long as you don’t save thisfailureHandler
(and other closures) as stored properties, you should be fine. But don’t just throw in a[weak self]
because you read somewhere that you should always use weak references. Use weak references where you need to avoid strong reference cycles, which would not appear to be the case here.The other alternative is to refactor this code, moving this network request routine,
dataRequest(input:)
to some more long-lived object.E.g., we often have a long-lived network manager object that maintains the
URLSession
and has all these network related methods. Then, assuming you’re keeping a strong reference to this network manager instance elsewhere, you don’t need to worry about the object being deallocated when it falls out of scope. This also saves you from having to pass in theURLSession
object for every request. A caller should not be dealing with theseURLSession
instances, anyway.For example, I often use a singleton network layer (kind of equivalent to
URLSession.shared
pattern):final class NetworkManager {
static let shared = NetworkManager()
private var session: URLSession = .shared // or create and configure this session as you need; but one session object is all you need
private init() { }
@discardableResult
func performRequest(...) -> URLSessionTask {
...
let task = session.dataTask(...) { [weak self] data, response, error in
...
}
task.resume()
return task
}
}Then you can do things like:
NetworkManager.shared.performRequest(...) { [weak self] ... in
...
}The other alternative is to just keep a strong reference to this
customNetworker
variable (e.g. make it a property rather than a local variable). That will prevent theCustomNetworker
object from falling out of scope and becomingnil
because there are no more strong references to it.
Somewhat unrelated, but it would appear that you are creating a URLSession
object when you instantiate your CustomNetworker
object, and subsequently never invalidate it. This will leak. You should create a single URLSession
object and use it for all subsequent network requests.
If you do create multiple URLSession
objects, you must invalidate each one when you’re done with it (e.g., finishTasksAndInvalidate
), or else you will leak. But if you just have one session that you keep alive for all future network requests (which is preferred), then that is not necessary.
Related Topics
Changing Navigation Bar Color in Swift
Why Do We Use Use_Frameworks! in Cocoapods
How to Open File and Append a String in It, Swift
Xcode 8 - Ib Designables - Failed to Render and Update Auto Layout Status, the Agent Crashed
How to Set Cg_Context_Show_Backtrace Environmental Variable
How to Make a Background Image Scale to Screen Size in Swift
Autolayout with Hidden Uiviews
How to Make Uitextview Height Dynamic According to Text Length
Uitextview - Setting Font Not Working with iOS 6 on Xcode 5
Retrieve All Contacts Phone Numbers in iOS
Dynamically Changing Font Size of Uilabel
Drawing Class Drawing Straight Lines Instead of Curved Lines
How to Draw a Line Programmatically from a View Controller
Attempt to Insert Non-Property List Object When Trying to Save a Custom Object in Swift 3
Ios9 Does Not Load Insecure Resources from a Secure Page (Ssl/Https)