为什么以下代码在Xcode playground中运行时会抛出fatal error: unexpectedly found nil while unwrapping an Optional value
?我不确定以下代码有什么问题。谢谢你的帮助。我还没试过在游乐场外跑步。
import UIKit
import XCPlayground
class CircularProgressView: UIView {
var progressBackgroundLayer: CAShapeLayer!
var progressLayer: CAShapeLayer!
var iconLayer: CAShapeLayer!
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
convenience init() {
self.init(frame: CGRectZero)
}
func setup() {
progressBackgroundLayer = CAShapeLayer(layer: layer)
progressLayer = CAShapeLayer(layer: layer)
iconLayer = CAShapeLayer(layer: layer)
}
override func drawRect(rect: CGRect) {
progressBackgroundLayer.frame = self.bounds
progressLayer.frame = self.bounds
iconLayer.frame = self.bounds
}
}
var progressView = CircularProgressView(frame: CGRectMake(0, 0, 80, 80))
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
XCPlaygroundPage.currentPage.liveView = progressView
答案 0 :(得分:2)
您不应使用init(layer:)
初始化程序来创建CAShapeLayers
。 From the documentation(强调我的):
此初始值设定项用于创建图层的阴影副本,例如,用于presentationLayer方法。 在任何其他情况下使用此方法将产生未定义的行为。例如,不要使用此方法初始化具有现有图层内容的新图层。
因此,由于在这种情况下调用此初始化器的行为未定义,它会在您的情况下返回nil
- 然后您在访问时强制解包,因为它是一个隐式解包的可选项。
您应该只使用init()
创建图层。我还建议您内联定义图层实例,并删除隐式展开的选项,如they're inherently unsafe。例如:
class CircularProgressView: UIView {
let progressBackgroundLayer = CAShapeLayer()
let progressLayer = CAShapeLayer()
let iconLayer = CAShapeLayer()
...
要将图层添加到视图中,您需要在视图图层上使用addSublayer:
方法。例如:
func setup() {
layer.addSublayer(progressBackgroundLayer)
layer.addSublayer(progressLayer)
layer.addSublayer(iconLayer)
}
此外,drawRect:
用于绘制视图的内容,因此完全是定义图层框架的错误位置(只应在视图边界发生变化时才会出现)。您应该考虑在layoutSubviews
中执行此操作。
override func layoutSubviews() {
progressBackgroundLayer.frame = bounds
progressLayer.frame = bounds
iconLayer.frame = bounds
}
最后,这段代码毫无意义:
convenience init() {
self.init(frame: CGRectZero)
}
这正是UIView
已init
实施的原因。