在Swift 1.2中将self作为参数传递给init方法

时间:2015-04-14 15:46:12

标签: ios xcode swift

以下课程有' let'声明为隐式展开变量的属性。这之前使用过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) {
        // ...
    }
}

更新到Xcode 6.3(使用Swift 1.2)后,会发生以下编译错误:

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

super.init来电之前移动以下行:

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

给出以下错误:

'self' is used before super.init call

该物业' panGestureRecognizer'不需要突变,因此必须将其声明为常数' let'。由于它是常量,因此必须在声明时具有初始值,或者在init方法中初始化它。要初始化它,需要通过' self'在' target'参数。

其他线程建议将其声明为隐式解包可选,并在super.init调用后初始化它。之前我已经更新到Xcode 6.3。

有没有人知道这种情况的正确实施或解决方法?

5 个答案:

答案 0 :(得分:12)

问题

问题在于您使用let - 声明为let的选项未被赋予默认值nil(但是var)。以下是在Swift 1.2中引入的,否则无效,因为在声明之后你将无法给myOptional一个值:

let myOptional: Int?

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

因此,您收到错误“属性”self.panGestureRecognizer'未在super.init调用中初始化',因为在调用super.init(coder: aDecoder)之前,因为panGestureRecognizer不是nil;它根本没有初始化。

解决方案:

1。panGestureRecognizer声明为var,这意味着它会被赋予默认值nil,然后您可以在调用{{}后更改1}}。

2。在我看来,更好的解决方案是:不要使用隐式展开的可选项,并声明super.init(coder: aDecoder)的初始值为panGestureRecognizer。然后在调用UIPanGestureRecognizer()后设置目标:

super.init

答案 1 :(得分:4)

除非初始化了类,否则您无法使用self。如果您想使用self进行属性初始化,则必须为lazy。但lazy不支持let,只有var

那是因为:

  

您必须始终将惰性属性声明为变量(使用var   关键字),因为它的初始值可能直到之后才被检索   实例初始化完成。常量属性必须始终   在初始化完成之前有一个值,因此不能   宣称是懒惰的。

这是一种妥协,如果你能和私人制定者一起生活,你可以这样做:

class SubView: UIView {

  private(set) lazy var panGestureRecognizer: UIPanGestureRecognizer = { [unowned self] in UIPanGestureRecognizer(target: self, action: "panAction:") }()

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

  func panAction(gesture: UIPanGestureRecognizer) {
  }
}

或仅使用panGestureRecognizer初始化UIPanGestureRecognizer()并稍后添加目标。

答案 2 :(得分:3)

此特定案例的解决方法是:

class SubView: UIView {

let pandGestureRecognizer: UIPanGestureRecognizer

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

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

}

答案 3 :(得分:0)

如果要将self传递给对象的初始值设定项,则应将对象声明为lazy。因为初始化此对象时,self还没有准备好。

lazy var viewModel = IntroViewModel(controller: self)

class IntroViewModel {

    private weak var controller: IntroViewController?

    init(controller: IntroViewController?) {
        self.controller = controller
    }
}

答案 4 :(得分:0)

由于另一个原因,我遇到了这个问题,它与Optionals无关。从字面上看,person对象必须初始化一次。

class Person {
    var name: String
    init(name: String) {
        self.name = name
    }
}

class Account {
    static let shared = Account(person: Person(name: "Bobby")) // <-- person initialized once
    let person: Person = Person(name: "Lio") // initialized again!

    init(person: Person) {
        self.person = person
    }
}

Swift可以捕获此错误很有趣