Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass self as argument within init method in Swift 1.2

Tags:

xcode

ios

swift

The following class has a 'let' property declared as implicitly unwrapped variable. This previously worked with Xcode 6.2:

class SubView: UIView {

    let pandGestureRecognizer: UIPanGestureRecognizer!

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.pandGestureRecognizer = UIPanGestureRecognizer(target: self, action: "panAction:")
    }

    func panAction(gesture: UIPanGestureRecognizer) {
        // ...
    }
}

After updating to Xcode 6.3 (with Swift 1.2), the following compilation errors occur:

Property 'self.panGestureRecognizer' not initialized at super.init call
Immutable value 'self.panGestureRecognizer' may only be initialized once

Moving the following line before the super.init call:

self.pandGestureRecognizer = UIPanGestureRecognizer(target: self, action: "panAction:")

gives the following error:

'self' is used before super.init call

The property 'panGestureRecognizer' requires no mutation, therefore it has to be declared as constant 'let'. Since it is a constant, it has to have an initial value upon declaration, or initialize it within the init method. To initialize it, it requires to pass 'self' in the 'target' parameter.

Other thread suggested to declare it as implicitly unwrapped optional, and initialize it after the super.init call. This previously worked until I updated to Xcode 6.3.

Does anybody know a proper implementation or a workaround for this case?

like image 347
Pette Avatar asked Apr 14 '15 15:04

Pette


1 Answers

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:"))
    }
}
like image 155
ABakerSmith Avatar answered Sep 27 '22 22:09

ABakerSmith