我想使用let
设置一个变量,这样它不是可选的,不会随着时间的推移而改变,并且每次都不需要杂乱的解包。我知道我可以合法地设置它,但只能在其中一个init
方法中。问题是Swift要求您覆盖init(coder aDecoder: NSCoder)
初始值设定项。但是我从来没有一个应用程序曾经调用过初始化程序。它始终是被调用的init(frame: CGRect)
初始值设定项。因此,如果我不必覆盖init(coder aDecoder: NSCoder)
,那么我只需执行self.imageView = UIImageView.new()
中的init(frame: CGRect)
即可完成,但编译器会抱怨其未设置在另一个中init也是。我尝试使用从两个inits调用的sharedInit()
方法,但编译器不允许我从那里设置imageView
,因为它只在init方法之外读取。如果不在init方法中直接执行所有init两次,你应该怎么做呢?
class SuperCoolView : UIView {
let imageView: UIImageView
required init(coder aDecoder: NSCoder) {
sharedInit()
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
sharedInit()
super.init(frame: frame)
}
func sharedInit() {
self.imageView = UIImageView.new()
// Other similar shared init
}
}
答案 0 :(得分:2)
只需使用延迟初始化和私有'set'的组合来获取:
class SuperCoolView : UIView {
public private(set) lazy var imageView: UIImageView = {
// In practice, do more here. Access state in this instance.
// Or, include more computation.
UIImageView.new()
}()
// inits w/o setting imageView
}
'私人套装'使其外部与let
相同; lazy
允许您根据SuperCoolView
实例中的其他状态初始化值。
请注意,如果imageView和其他的初始化不依赖于实例中的状态,那么您可以避免使用lazy
并从闭包中进行初始化。
答案 1 :(得分:2)
我发现this answer并且喜欢它的方法。它修复了问题,并且更加清洁恕我直言。通过实现init(coder aDecoder: NSCoder)
通常我们会保持这样的外观,即当它不能时,可以从笔尖/故事板初始化该视图。
class SuperCoolView : UIView {
let imageView: UIImageView
required init(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
override init(frame: CGRect) {
self.imageView = UIImageView.new()
// Other stuff
super.init(frame: frame)
}
}