Reputation: 1404
I have following code from playground:
class MyButton {
var pressed: (() -> Void)?
func press() {
pressed?()
}
}
class SomeView {
var buttonDidPressed: (() -> Void)?
let button = MyButton()
init() {
button.pressed = buttonDidPressed
}
func press() {
button.press()
}
}
let view = SomeView()
view.buttonDidPressed = {
print("pressed")
}
view.press()
MyButton
has closure pressed
which is executed when press
is called. In SomeView
s init, I assign value to that pressed
closure. Of course, at the init, it is nil
. But after initialization of SomeView
, I assign value to that buttonDidPressed
closure. Because, closures are reference type, when view.press
is called, buttonDidPressed
should not be nil. But, anyway, my print is not executed. Why?
Upvotes: 3
Views: 354
Reputation: 49610
Here's what I think you want to achieve:
class SomeView {
var buttonDidPressed: (() -> Void)? = nil {
didSet {
button.pressed = buttonDidPressed
}
}
let button = MyButton()
func press() {
button.press()
}
}
The reason your code isn't working is because in the SomeView.init
, buttonDidPressed
is nil
- i.e. it's a lack of reference. So:
buttonDidPressed = nil
button.pressed = buttonDidPressed
// is equivalent to
button.pressed = nil
Assigning a new (or different) reference to buttonDidPressed
later doesn't change the button.pressed
property.
Upvotes: 1
Reputation: 8347
You first initialize SomeView
(the init
function gets called) and then you set the buttonDidPressed
property. So, the buttonDidPressed
property has your closure but never passed it to MyButton
instance.
You can use didSet
to update it immediately:
class SomeView {
var buttonDidPressed: (() -> Void)? {
didSet {
button.pressed = buttonDidPressed
}
}
let button = MyButton()
func press() {
button.press()
}
}
Update: You can also pass your closure in the initializer of SomeView
like this:
class SomeView {
let button = MyButton()
init(buttonDidPressed: (() -> Void)?) {
button.pressed = buttonDidPressed
}
func press() {
button.press()
}
}
let view = SomeView {
print("pressed")
}
view.press()
Upvotes: 2
Reputation: 201
Actually it is better to explain with this issue by using binding, Let`s say :
class Sekoya<T> {
typealias Listener = (T) -> Void
var listenerHolder: Listener?
var value: T {
didSet {
listenerHolder?(value) // when value change listenerHolder triger
}
}
init(_ value: T) {
self.value = value
}
func bind(listener: Listener?) {
self.listenerHolder = listener // referencing listener my closure variable in SomeView Class
listener?(value)
}
}
Lets use this binding at the another class:
let sekoyaInt = Sekoya(25)
sekoyaInt.bind {
print("value changed: \($0)")
}
Whenever you change the value your reference closure will be trigger and value will be change and it prints value
Upvotes: 1