簡體   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