Add [unowned self] to the closure argument Swift
As I said in my comment
Struct().function { [unowned self] (string) in
//your code here
}
Capture list and closure parameters that should be the order in closures more info from Apple Documentation
Defining a Capture List
Each item in a capture list is a pairing of
the weak or unowned keyword with a reference to a class instance (such
as self) or a variable initialized with some value (such as delegate =
self.delegate!). These pairings are written within a pair of square
braces, separated by commas.Place the capture list before a closure’s parameter list and return
type if they are provided:
lazy var someClosure: (Int, String) -> String = {
[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// closure body goes here
}
If a closure does not specify a parameter list or return type because
they can be inferred from
context, place the capture list at the very start of the closure,
followed by the in keyword:
lazy var someClosure: () -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
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
Related Topics
Why Does User Defaults Publisher Trigger Multiple Times
Swift Initialization Rule Confusion
How to Convert an Array to List in Realm
How to Calculate The Camera Position from Vuforia Gl Matrix
Dynamic Links Firebase Function Not Being Called at All Xcode 12
Rlmexception', Reason: 'Attempting to Modify Object Outside of a Write Transaction
Parse Migration Error to Mlabs and Heroku
Swift Error "Static Member Cannot Be Used on Instance of Type"
Why Do I Get Rgb Values of (0,0,0) for an Nsimage with a Transparent Background
Reduce Float Precision Using Regexp in Swift
Appdelegate#Applicationdidfinishlaunching Not Called for Swift 4 Macos App Built from Command Line
Cannot Authenticate User for Aws Appsync with Swift Sdk
Can Not Get Correct Position of View in Swiftui
Flattened Objects in JSON File to Nested Object Structure in Swift
How to Make First Responder in Swiftui Macos
How to Synchronize Access to a Property That Has Didset