41

Here is the layout of an example Class, can someone guide me on what's best practice when creating a subclass of NSObject?

class MyClass: NSObject {

    var someProperty: NSString! = nil

    override init() {
        self.someProperty = "John"
        super.init()
    }

    init(fromString string: NSString) {
        self.someProperty = string
        super.init()
    }

}

Is this correct, am I following best practice here?

I wonder if I'm correctly setting up the initializers (one that sets the string to a default, and one which I can pass in a string)?

Should I call super.init() at the end of each of the initializers?

Should my more specific (the one that takes a string) initializer simply call self.init() at the end rather than super.init()?

What is the right way to set up the initializers in Swift when subclassing NSObject? - and how should I call the super init ?

This question (albeit in Objective C) suggests you should have an init, which you always call and simply set the properties in more specific inits: Objective-C Multiple Initialisers

Community
  • 1
  • 1
Woodstock
  • 22,184
  • 15
  • 80
  • 118
  • 1
    *The Swift Programming Language* has an [entire chapter on initialization](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_306), covering inheritance, designated vs. convenience initializers, and so on. The process is significantly different than Objective-C (and to me feels more complex/nuanced), so definitely read that to understand better what to do. – Nate Cook Aug 16 '14 at 21:58

3 Answers3

65

I'm not Swift ninja but I would write MyClass as:

class MyClass: NSObject {
    
    var someProperty: NSString // no need (!). It will be initialised from controller 
    
    init(fromString string: NSString) {
        self.someProperty = string
        super.init() // can actually be omitted in this example because will happen automatically.
    }
    
    convenience override init() {
        self.init(fromString:"John") // calls above mentioned controller with default name
    }        
}

See the initialization section of the documentation

malhal
  • 26,330
  • 7
  • 115
  • 133
Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • What if you want to init multiple properties? One is a string, another is a NSNumber, an array, etc..... – Supertecnoboff Mar 30 '18 at 09:42
  • @Supertecnoboff you would add each of them into the initialiser method, ie: ```init(with name: NSString, age: NSNumber, children: [NSString]) { self.name = name self.age = age self.children = children super.init() }``` – user1898712 Jan 18 '19 at 14:59
2

If someProperty can be nil, then I think you want to define the property as:

var someProperty: NSString?

This also eliminates the need for a custom initializer (at least, for this property), since the property doesn't require a value at initialization time.

Jed Lau
  • 326
  • 1
  • 3
  • 9
0

In complement to the answers, a good idea is to call super.init() before other statements. I think it's a stronger requirement in Swift because allocations are implicit.

tontonCD
  • 320
  • 2
  • 6
  • 6
    You cannot call `super.init()` prior to initializing non-optional fields that do not have a default value in their declaration. In this case it would work because the property is an optional type: `NSString!`. – Charles A. Apr 30 '18 at 22:49