bobawgg
bobawgg

Reputation: 107

Unable to reference self in closure when defining property

I saw this example online somewhere:

let newButton:UIButton = {
   let button = UIButton()

    return button
}()

when I add:

button.addTarget(self, action: Selector("someAction"), forControlEvents: UIControlEvents.TouchUpInside)

I receive the error message:

Cannot convert value of type 'NSObject -> () -> ViewController' to expected argument type 'AnyObject?'

Just looking for clarification on why I cannot reference self here and how I can potentially make this work.

Upvotes: 2

Views: 93

Answers (2)

Charles A.
Charles A.

Reputation: 11123

Assuming you're writing this inside of a class scope (not inside a method, etc). Based on a little experimentation, it seems that self will be a reference to the class type, not an instance. This is probably because in Swift you cannot reference self during the initialization process prior to all fields being initialized and any necessary calls to an initializer on super happening.

If you need the property to be a constant, you would have to do this in an initializer, obeying the order requirements for initialization:

let newButton: UIButton

init() {
    newButton = UIButton()

    super.init()

    button.addTarget(self, action: Selector("someAction"), forControlEvents: UIControlEvents.TouchUpInside)
}

Upvotes: 0

Daniel Klöck
Daniel Klöck

Reputation: 21137

You cannot reference self because the constant gets set before self is initialised.

You could solve the issue by declaring it as lazy var instead of let. By declaring it lazy var you are telling that you want the var to be initialised the first time it is used:

lazy var newButton: UIButton = {
    let button = UIButton()
    button.addTarget(self, action: Selector("someAction"), forControlEvents: UIControlEvents.TouchUpInside)

    return button
}()

As a side note, with Swift 2.2 you should define selectors as #selector(YourClass.someAction)

Upvotes: 2

Related Questions