user12345 user12345 - 5 months ago 10
iOS Question

When to initialise viewController global variables using swift

I come from an Objective C background and I'm normally used to declaring my properties (global variables to the class) inside the init method of a given class i.e. something like this:

-(instancetype) init {
self = [super init];
if(self){
self.viewModel = [[MyViewModel alloc] init:self];
}
return self;
}


When self.viewModel is a property and I normally pass the a view controller as a parameter to the view model for callback purposes. I'm currently trying to do the same in swift.

I have a normal a custom view controller class, with the following init method:

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nil, bundle: nil)
self.viewModel = SearchViewModel(callback: self)
}


Now with the code above, xcode complains that


self.viewModel has not been initialised


However when I try initialise the viewModel i.e:

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
self.viewModel = SearchViewModel(callback: self)
super.init(nibName: nil, bundle: nil)
}


I then get


self used before super.init call


How would I sort this out in Swift?

Answer

First off: Swift initializers want all properties of self to be set up properly / to have a value before calling a super initializer.

Second off: You mustn't use self before the super.init-call because otherwise the properties that you would set in the super constructor are not yet set meaning whoever receives the non-finished self-instance can not be sure about the state of self.

Solution: Make viewModel of type SearchViewModel! and use the first code alternative.

Explanation: By making viewModel an implicitly unwrapped optional it implicitly contains nil in the beginning, therefore you can now call super.init and set an actual value to viewModel after that.

Comments