繁体   English   中英

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

[英]Pass self as argument within init method in Swift 1.2

以下类具有声明为隐式展开变量的' 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方法中初始化它。 要初始化它,需要在' target '参数中传递' self '。

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

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

问题

问题是你使用let -optionals声明为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 ,然后在调用super.init(coder: aDecoder)之后可以更改。

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

class SubView: UIView {
    let panGestureRecognizer = UIPanGestureRecognizer()

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

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

除非初始化类,否则不能使用self 如果你想使用self进行属性初始化,它必须是lazy 但是let不支持lazy ,只是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) {
  }
}

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

针对此特定情况的解决方法是:

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) {
    // ...
}

}

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

lazy var viewModel = IntroViewModel(controller: self)

class IntroViewModel {

    private weak var controller: IntroViewController?

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

我有这个问题的原因不同,它与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可以捕获这个错误,这很有趣

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM