Andree
Andree

Reputation: 3103

Referring to self during property declaration in Swift

I'm trying to declare and initialize a property with the following code.

class ClassName: UIViewController {

  private let doneButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "doneButtonDidTapped")

   func doneButtonDidTapped() {
      println("Ulala!")
   }
}

However, I got the following error.

Cannot find an initializer for type 'UIBarButtonItem' that accepts an argument list of type '(title: String, style: UIBarButtonItemStyle, target: ClassName -> () -> ClassName, action: String)'

Anybody know what's going on here? Should I give up my attempts to initialize the property inline with the declaration and do the initialization on init() method instead?

Upvotes: 1

Views: 794

Answers (3)

stevesw
stevesw

Reputation: 1065

The closure in @agy's answer is unnecessary, you can just do (in Swift 3):

lazy var button:UIBarButtonItem = UIBarButtonItem(title: "Title", style: .plain, target: self, action: #selector(buttonPressed(_:)))

Upvotes: 2

agy
agy

Reputation: 2854

As @giorashc says due to swift's 2-phase initialization, self is not yet initalized so you cannot do it.

But I think you could create a lazy inialization:

lazy private var doneButtonItem : UIBarButtonItem = {
    [unowned self] in
    return UIBarButtonItem(title: "Done", style:UIBarButtonItemStyle.Plain, target: self, action: "doneButtonDidTapped")
    }()

Upvotes: 7

giorashc
giorashc

Reputation: 13713

Due to swift's 2-phase initialization you need to initialize the parent class before you can use self in the inheriting class.

In your implementation self is yet to be initialized by the parent class so as you said you should move it to the init method of your view controller and create the button after calling the parent's initialization method

Upvotes: 1

Related Questions