Swift Error Using Initialized Properties in Expressions Before Super.Init

Swift error using initialized properties in expressions before super.init

This is a side-effect of || being declared as

func ||<T : BooleanType>(lhs: T, rhs: @autoclosure () -> Bool) -> Bool

So the compiler treats

true || myProperty

as

true || { self.myProperty }()

The reason is the "short-circuiting" behaviour of the || operator: If the first
operand is true, then the second operand must not be evaluated at all.

(Side note: I assume that this is simplified at a later stage in the
compiling/optimizing process
so that the final code does not actually create and call a closure.)

Accessing self inside the closure causes the error message. You would
get the same error for

override init() {
myProperty = true
let a = { self }() // ERROR: self used before super.init
super.init()
let b = { self }() // OK after super.init
}

swift Property not initialized at super.init call

You can fix this by adding a line to set notificationStyle to a default value in init?(coder aDecoder: NSCoder):

required init?(coder aDecoder: NSCoder) {
self.notificationStyle = .numberedSquare //<-- Here
super.init(coder: aDecoder)
setup(notificationStyle: notificationStyle)
}

You have to do this because in your declaration of notificationStyle, there's no default value and it must have a value before calling super.init. In your other initializers, you set it based on the incoming arguments.

This is an initializer that it sounds like you're not using anyway, but it is required with UIViews that we implement this required initializer.

Swift super.init() - Property not initialized at super.init call

Replace

fileprivate var directionsCompletionHandler:DirectionsCompletionHandler

with

fileprivate var directionsCompletionHandler: DirectionsCompletionHandler = nil

Error in Swift class: Property not initialized at super.init call - How to initialize properties which need use of self in their initializer parameter

You just have to invert the order super.init/properties in your initializer:

 required init(coder aDecoder: NSCoder) {
self.datasourceOfflineVideos = ASDataSource(tableViewController: self)
self.datasourceOnlineVideos = ASDataSource(tableViewController: self)
super.init(coder: aDecoder)
}

instance properties comes first, then the superclass initializer can be invoked. But that's not possible in your case, because you are referencing self.

The workaround in this case is to make the properties implicitly unwrapped optionals:

var datasourceOnlineVideos:ASDataSource!
var datasourceOfflineVideos:ASDataSource!

Since optionals don't need to be initialized, you can safely initialize them after the super.init method has been called. Being implicitly unwrapped, you use them as any other non optional property.

This pattern is used by Apple in several classes, including UIViewController: when you add an outlet from IB, the component property is always declared as implicitly unwrapped. That's because the control itself is not instantiated in the initializer, but at a later stage.

In swift I cant initialize things before the super.init() or after

This is exactly what implicitly unwrapped optionals are good for. You can easily add them to your example like this:

/***  Initializers  ***/
init(frame: NSRect) {
super.init(frame: frame)
subviewGroup = GridViewGroup(rows: 9, columns: 9, gridView: self)
}

/*** Properties ***/
let subviewGroup: GridViewGroup!

Using an implicitly unwrapped optional allows you to treat the variable as if it weren't an optional and access the underlying directly when you call it.

Using a normal optional your code may look like var nonoptional: GridViewGroup = subviewGroup! while with implicitly unwrapped optionals you can discard the !: var nonoptional: GridViewGroup = subviewGroup.

From Apple's docs:

Implicitly unwrapped optionals are useful when an optional’s value is
confirmed to exist immediately after the optional is first defined and
can definitely be assumed to exist at every point thereafter. The
primary use of implicitly unwrapped optionals in Swift is during class
initialization

Order of setting variables and super.init in init, both give errors

You need to pass a Binding<Int> to the constructor:

    init(keycode : Binding<Int>){
self._keycode = keycode
super.init( // .....
}

Swift variable observers not called before super.init called

They are talking about following scenario:

class A {
var p: Bool {
didSet {
print(">>> didSet p to \(p)")
}
}

init() {
p = false // here didSet won't be called
}
}

class B: A {

override init() {
// here you could set B's properties, but not those inherited, only after super.init()
super.init()
p = true // here didSet will be called
}
}

B()

It will print following:

>>> didSet p to true

While to you it might seems natural, the documentation has to explicitly document this behavior.

Use of 'self' in property access 'model' before super.init initializes self super.init(brand: brand, model: model)

You are calling the superclass init method to initialize part of your subclass. However, before you have initialized it, you passed an uninitialized variable. Simply add those variables into the parameter of the Piano:

init(hasPedals: Bool, brand: String, model: String)

What's the purpose of initializing property values before calling super designated initializer in swift?

Your argument

I think this should be compiled:

y is not visible inside class 'Base',whether order of initializations
of y's and super class's doesn't really matter.

is not correct, that would not be safe.

The superclass init can call an instance
method which is overridden in the subclass. That is (at least one)
reason why all subclass properties must be initialized before super.init() is called.

A simple example:

class Base
{
init(){
print("enter Base.init")
setup()
print("leave Base.init")
}

func setup() {
print("Base.setup called")
}
}

class Test : Base
{
internal var y:Int
override init()
{
y = 123
print("before super.init")
super.init()
print("after super.init")
}

override func setup() {
print("Test.setup called")
print("y = \(y)")
}
}

Output:


before super.init
enter Base.init
Test.setup called
y = 123
leave Base.init
after super.init

As you can see, the y property of the subclass is accessed
during the super.init() call, even if it is not known to the
superclass.


It might be interesting to compare the situation in Objective-C
where self = [super initXXX] is always called first. This has the
consequence that property access self.prop in init/dealloc methods
is unsafe and direct access to the instance variable _prop is
recommended because the object may be in a "partially constructed state".
See for example Should I refer to self.property in the init method with ARC?.

So this is one of the issues which have been solved in Swift
(at the cost of stricter requirements).



Related Topics



Leave a reply



Submit