在Swift 1.2的init方法中将自身作为parameter passing
下面的类有一个“ let
”属性声明为隐式解包variables。 以前在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
'。
其他线程build议将其声明为隐式解包可选,并在super.init
调用之后对其进行初始化。 这之前工作,直到我更新到Xcode 6.3。
有没有人知道这种情况下的正确实施或解决方法?
问题
问题是你使用let
– optionals声明为let
没有被赋予一个默认值nil
( var
是然而)。 在Swift 1.2中引入的以下内容将是无效的,因为在声明之后,您将无法给myOptional
一个值:
let myOptional: Int? if myCondition { myOptional = 1 } else { myOptional = nil }
因此,在调用super.init(coder: aDecoder)
之前,你得到的错误是'Property'self.panGestureRecognizer'没有在super.init调用中初始化',因为panGestureRecognizer
不是nil
; 它还没有被初始化。
解决scheme:
1.将 panGestureRecognizer
声明为var
,这意味着它将被赋予一个默认值nil
,然后你可以在调用super.init(coder: aDecoder)
之后改变它。
2.在我看来,更好的解决scheme:不要使用隐式解包的可选项,并声明与UIPanGestureRecognizer()
的初始值UIPanGestureRecognizer()
。 然后在调用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
。 但lazy
不支持let
,只是var
。
那是因为:
您必须始终将lazy属性声明为variables(使用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) { // ... }
}