I have:
private var statusLabel: UILabel!
private var errorObserver: NSKeyValueObservation?
self.errorObserver = self.viewModel.observe(\.errorString)
{ [weak self] (viewModel, change) in
self?.statusLabel.text = viewModel.errorString
}
Is [weak self]
needed here?
Short answer: Yes, you do need the [weak self]
. Not having to explicitly remove the observer in deinit
is a nice convenience that makes sure the Observation Center does not send notifications to de-initialized observers, but does not absolve you from having to manage memory for the closure.
Apple's Official Documents (The Swift Programming Language 4.0.3) states:
By default, a closure expression captures constants and variables from its surrounding scope with strong references to those values. You can use a capture list to explicitly control how values are captured in a closure.
A capture list is written as a comma-separated list of expressions surrounded by square brackets, before the list of parameters. If you use a capture list, you must also use the in keyword, even if you omit the parameter names, parameter types, and return type.
....
If the type of the expression’s value is a class, you can mark the expression in a capture list with weak or unowned to capture a weak or unowned reference to the expression’s value.
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 4.0.3).” iBooks.
If you do not mark the expression self
in a capture list, a strong reference cycle will be created. A strong reference cycle is created because classes are reference types, and closures are reference types. When the body of the closure refers to an instance of a class, a reference to the class instance is created by the closure. By default, this is a strong reference, unless you use a capture list to define a different type of reference. The official notes even say:
Swift requires you to write
self.someProperty
orself.someMethod()
(rather than justsomeProperty
orsomeMethod()
) whenever you refer to a member ofself
within a closure. This helps you remember that it’s possible to captureself
by accident.
In your case, you are referencing a label inside the body of the closure. The fact that you need to write
self?.statusLabel.text = viewModel.errorString
instead of simply
.statusLabel.text = viewModel.errorString
is a hint to you to use self
inside a capture list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With