Initializing Swift Properties That Require "Self" as an Argument

Initializing Swift properties that require self as an argument

You've found the primary use case of the Implicitly Unwrapped Optional.

  • You need to access self from init, before timer is initialized.
  • Otherwise, timer should never be nil, so you shouldn't have to check it outside of init.

So, you should declare let timer: NSTimer!.

Pass self as argument within init method in Swift 1.2

The Problem

The problem is your use of let - optionals declared as let aren't given a default value of nil (var is however). The following, introduced in Swift 1.2, wouldn't be valid otherwise since you wouldn't be able to give myOptional a value after declaring it:

let myOptional: Int?

if myCondition {
myOptional = 1
} else {
myOptional = nil
}

Therefore, you're getting the error 'Property 'self.panGestureRecognizer' not initialized at super.init call' because before calling super.init(coder: aDecoder), because panGestureRecognizer isn't nil; it hasn't been initialised at all.

The Solutions:

1. Declare panGestureRecognizer as a var, meaning it will be given a default value of nil, which you could then change after calling super.init(coder: aDecoder).

2. In my opinion, the better solution: don't use an implicitly unwrapped optional and declare panGestureRecognizer with an initial value of UIPanGestureRecognizer(). Then set the target after super.init is called:

class SubView: UIView {
let panGestureRecognizer = UIPanGestureRecognizer()

required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)

panGestureRecognizer.addTarget(self, action: Selector("panAction:"))
}
}

How can I initialize a class property that depends on an initializer argument as well as `self`?

An alternative is to declare consumer in Supplieras weak optional to avoid a retain cycle (Consumer holds a strong reference to Supplier and vice versa)

class Consumer
{
let supplier: Supplier

init(observer: Observer)
{
self.supplier = Supplier(observer: observer)
supplier.consumer = self
}
}

class Observer {}

class Supplier
{
let observer : Observer
weak var consumer : Consumer?

init(observer: Observer, consumer: Consumer? = nil) {
self.observer = observer
self.consumer = consumer
}
}

And this is Swift: No trailing semicolons.

init let properties with reference to self in subclass in swift

This is a good use case for an implicitly unwrapped optional.

The Apple documentation states:

“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.”

This means that you can use an implicitly unwrapped optional when a property depends on some aspect of self (but not the superclass) when it is initialised.

The property will be nil until it is set in the init() method and then must never be nil again.

class NodeView: UIView {

var _nodePlugView: NodePlugView!

init (node: Node) {
super.init()
_nodePlugView = NodePlugView (parentView: self)
}
}

Is it possible to initialize properties at the beginning of a class?

You have to initialize all instance properties somehow. And you have to do it right up front, either in the declaration line or in your init method.

But what if you don't actually have the initial value until later, like in viewDidLoad? Then it is silly to supply a real heavyweight value only to replace it later:

var v = MyView()
override func viewDidLoad() {
self.v = // get _real_ MyView and assign it in place of that
}

Instead, we use an Optional to mark the fact that we have no value yet; until we obtain and assign one, it will be nil:

var v : MyView? // means it is initially `nil`
override func viewDidLoad() {
self.v = // get _real_ MyView and assign it to our property
}

Why can i use self when I initialize property with a closure?

The target in your code is probably nil, the reason that this might work is that:

...If you specify nil, UIKit searches the responder chain for an
object that responds to the specified action message and delivers the
message to that object

(from the documentation of the method)

You can verify that the target is actually nil by setting a breakpoint during or after your controller's init and by inspecting the _targetActions array (in the debugger's variables view) of the button (you can see that target's address is 0x0).

In your example, loginRegisterButton is set during the controller's initialization which means that there is no self yet (in other words you cannot guarantee that all instance variables are initialized at this point). The way lazy solves this is that the actual assignment is deferred on first access.

Property initializers run before 'self' is available

As correctly pointed out by vadian you should create an init in such scenarios:

class MyOwn {
let myUser: User
var life: Int

init() {
self.myUser = User(name: "John", age: 100)
self.life = myUser.age
}
}

You can't provide a default value for a stored property that depends on another instance property.

swift init properties with self or not?

You can use without self, but the field variable need be different than outside variable.

Why?

Simple, variables in field is constant statement (let) init(sideLength: Double, name: String) sideLenght and name in this line are constants variables, because this you can't set new value for it.

ps. let in swift is same than const in other language

Ex.

example why can't use same name without self

The correct way to implement is with self., because in this case we tell to compiler to set the variable outside in our class.

example using variable with self

Other example now setting variable without self., look next image, we can use without self because it is outside variable.

example using name without self



Related Topics



Leave a reply



Submit