user1107173
user1107173

Reputation: 10764

Swift 3: Initializing UITableViewController

Subclassing from UITableViewController and I am getting two errors when trying to init the TVC class:

class TVC: UITableViewController {

  let vm: ViewModel

  override init(style: UITableViewStyle){
    super.init(style: style)
    self.vm = ViewModel(tvc: self) // Error: Property `self.vm` not initialized at super.init call
  }

  override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!){
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
  }

  required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
    // Error: Property `self.vm` not initialized at super.init call
  }

}

Error: Property self.vm not initialized at super.init call

The work around of making vm an optional (vm: ViewModel?) works, but I would like to it this way, if possible.

What am I doing wrong?

Upvotes: 0

Views: 791

Answers (3)

Mellong Lau
Mellong Lau

Reputation: 123

Actually, you can change

let vm: ViewModel

to

var vm: ViewModel?

the error will not be showed.

Upvotes: 0

Connor Neville
Connor Neville

Reputation: 7361

There are workarounds, namely making the view model lazy (see Alesenka's solution) or an implicitly unwrapped optional (var vm: ViewModel!) and initializing after self, but more important is figuring out your design pattern.

A view model shouldn't need to know about its controller; it just has the necessary information to populate the view, which the controller uses. Further, if you're actually holding on to the view controller after initializing the view model, they're both referencing each other, and you'll have a retain cycle. For these reasons, the best solution is to eliminate the need to pass in self to the view model.

Upvotes: 1

Alesenka
Alesenka

Reputation: 1

You could make vm lazy

lazy var vm: ViewModel = { 
  return ViewModel(tvc: self)
}()

So you don't have to init this property in init method

Upvotes: 0

Related Questions