![](/img/trans.png)
[英]Not able to pass self (which implements a protocol) to init method of a class instantiation.(Swift)
[英]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.