doovers doovers - 1 month ago 14
Swift Question

Force specific initialiser in Swift 3

I'm trying to create a class which inherits from NSObject that can only be initialised given the required parameters. I can achieve this as follows:

class MyTestClass: NSObject {
var myTestValue: String
var myTestValue2: String
var myTestValue3: String

private override init() {
myTestValue = ""
myTestValue2 = ""
myTestValue3 = ""
super.init()
}

init(value: String, value2: String, value3: String) {
myTestValue = value
myTestValue2 = value2
myTestValue3 = value3
super.init()
}
}


Is there a better way to achieve this without having to duplicate the initialisation of the class variables?

Obviously, optionals are an option here but I don't want to go that route. Any suggestions for a more concise way to achieve the same?

Answer

If I understand correctly, you're looking for a way to initialize an object of this class using only the values given in the initializer's parameter?

Would this suffice?

import Foundation

class MyTestClass: NSObject {
    let myTestValue: String
    let myTestValue2: String
    let myTestValue3: String

    init(myTestValue: String, myTestValue2: String, myTestValue3: String) {
        self.myTestValue = myTestValue
        self.myTestValue2 = myTestValue2
        self.myTestValue3 =  myTestValue3
        super.init()
    }
}

//...
MyTestClass() //Disallowed

Calling with no parameters gives this error:

ERROR at line 16, col 12: missing argument for parameter 'value' in call
MyTestClass()
           ^
INFO at line 8, col 5: 'init(value:value2:value3:)' declared here
    init(value: String, value2: String, value3: String) {
    ^

From the Swift Language guide:

Swift provides a default initializer for any structure or class that provides default values for all of its properties and does not provide at least one initializer itself. The default initializer simply creates a new instance with all of its properties set to their default values.

Depending on your needs, you can also use a struct. If no other initializers are provided, they provide a member wise initializer:

struct MyTestStruct {
    let myTestValue: String
    let myTestValue2: String
    let myTestValue3: String
}

// Implicit member-wise initializer:
_ = MyTestStruct(myTestValue: "a", myTestValue2: "b", myTestValue3: "c")