0

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?

doovers
  • 8,545
  • 10
  • 42
  • 70

1 Answers1

1

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")
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • Doh! I tried many ways but not that because I assumed that `NSObject`'s `init` would still be accessible! Not sure I understand why it isnt. Any idea? – doovers Oct 14 '16 at 02:44
  • Initializers are not inherited. See [this question](http://stackoverflow.com/questions/18147768/why-constructors-can-not-be-inherited-in-java) for the rationale. It's Java, but the idea applies to Swift. – Alexander Oct 14 '16 at 02:49
  • I think [this](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID217) section of the Swift Language guide might be more applicable since it's dealing with inheritance which is the case in my example. – doovers Oct 14 '16 at 02:59