隐式解包和初始化器
Implicit Unwrapping and Initializers
我有一个UIView
的子类,它实例化了几个子层。为了方便起见,我特别想要一个直接引用,因为它与视图具有相同的生命周期,所以将它设为 let 常量似乎是合理的。问题是我希望子层对其 owner/parent 视图有一个类似的不可变引用,所以我尝试将其传递给层的初始化程序:
class MyView: UIView{
let myLayer: MyLayer!
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
self.myLayer = MyLayer(owner: self) // <- The problem line.
self.layer.addSublayer(self.myLayer)
}
}
class MyLayer: CAShapeLayer {
unowned let owner: MyView
init(owner: MyView) {
self.owner = owner
super.init ()
}
}
如果我在调用 MyView
的 super.init
之前调用层初始值设定项,我会得到错误 “'self' used before 'super.init' call.”
我认为这是允许的(首选我总是想?)在 属性 初始化中使用 self
,但它还没有可以作为参数传递的值?
但是如果我把这一行放在 super.init 之后,如图所示,我会得到两个错误:“Property 'self.myLayer' not initialized at super.init call”
和 “Immutable value 'self.myLayer' may only be initialized once.”
这让我很困惑,因为我认为隐式解包可选的一点是它的声明中有一个有效的 nil
值,并且这不算作 let 语句允许的唯一赋值。 (这听起来也有点矛盾:有些东西没有初始化,但在尝试初始化之后,它最终还是被初始化了两次,是吗?)
我知道我可以通过放弃对不可变的痴迷来解决这个问题,但是有没有办法正确地做到这一点?我完全赞成Swift的安全检查,但这里真的有危险吗?我认为隐式展开会向编译器发出信号,表明程序员已意识到可能存在的问题并正在寻找后果。
我认为隐式解包可选的一点是它的声明中有一个有效的 nil 值,这不算是唯一的赋值 let声明允许。
不幸的是,它很重要。此更新后此行为已修复为当前样式:
Xcode Release Notes > Xcode 6.3 > Swift Language Changes
您可能已经找到了一些解决方法,但我认为这将非常接近您想要的:
class MyView: UIView {
private(set) var myLayer: MyLayer!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.myLayer = MyLayer(owner: self)
self.layer.addSublayer(self.myLayer) }
}
您可以为此使用惰性变量。它基本上是一个 let,只在第一次使用时初始化一次。
class MyView: UIView{
lazy var myLayer: MyLayer = {
return MyLayer(owner: self)
}()
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
self.layer.addSublayer(self.myLayer)
}
}
我有一个UIView
的子类,它实例化了几个子层。为了方便起见,我特别想要一个直接引用,因为它与视图具有相同的生命周期,所以将它设为 let 常量似乎是合理的。问题是我希望子层对其 owner/parent 视图有一个类似的不可变引用,所以我尝试将其传递给层的初始化程序:
class MyView: UIView{
let myLayer: MyLayer!
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
self.myLayer = MyLayer(owner: self) // <- The problem line.
self.layer.addSublayer(self.myLayer)
}
}
class MyLayer: CAShapeLayer {
unowned let owner: MyView
init(owner: MyView) {
self.owner = owner
super.init ()
}
}
如果我在调用 MyView
的 super.init
之前调用层初始值设定项,我会得到错误 “'self' used before 'super.init' call.”
我认为这是允许的(首选我总是想?)在 属性 初始化中使用 self
,但它还没有可以作为参数传递的值?
但是如果我把这一行放在 super.init 之后,如图所示,我会得到两个错误:“Property 'self.myLayer' not initialized at super.init call”
和 “Immutable value 'self.myLayer' may only be initialized once.”
这让我很困惑,因为我认为隐式解包可选的一点是它的声明中有一个有效的 nil
值,并且这不算作 let 语句允许的唯一赋值。 (这听起来也有点矛盾:有些东西没有初始化,但在尝试初始化之后,它最终还是被初始化了两次,是吗?)
我知道我可以通过放弃对不可变的痴迷来解决这个问题,但是有没有办法正确地做到这一点?我完全赞成Swift的安全检查,但这里真的有危险吗?我认为隐式展开会向编译器发出信号,表明程序员已意识到可能存在的问题并正在寻找后果。
我认为隐式解包可选的一点是它的声明中有一个有效的 nil 值,这不算是唯一的赋值 let声明允许。
不幸的是,它很重要。此更新后此行为已修复为当前样式:
Xcode Release Notes > Xcode 6.3 > Swift Language Changes
您可能已经找到了一些解决方法,但我认为这将非常接近您想要的:
class MyView: UIView {
private(set) var myLayer: MyLayer!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.myLayer = MyLayer(owner: self)
self.layer.addSublayer(self.myLayer) }
}
您可以为此使用惰性变量。它基本上是一个 let,只在第一次使用时初始化一次。
class MyView: UIView{
lazy var myLayer: MyLayer = {
return MyLayer(owner: self)
}()
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
self.layer.addSublayer(self.myLayer)
}
}