Swift drawRect抛出;致命错误:在展开可选值“时意外发现nil”;在Xcode操场
为什么下面的代码抛出Swift drawRect抛出;致命错误:在展开可选值“时意外发现nil”;在Xcode操场,swift,swift-playground,xcplayground,Swift,Swift Playground,Xcplayground,为什么下面的代码抛出致命错误:在Xcode中运行时,在展开可选值时意外发现nil?我不确定下面的代码有什么问题。谢谢你的帮助。我还没试过在操场外跑步 import UIKit import XCPlayground class CircularProgressView: UIView { var progressBackgroundLayer: CAShapeLayer! var progressLayer: CAShapeLayer! var iconLayer: C
致命错误:在Xcode中运行时,在展开可选值时意外发现nil
?我不确定下面的代码有什么问题。谢谢你的帮助。我还没试过在操场外跑步
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
您不应该使用
init(layer:)
初始化器来创建CAShapeLayers
。(我的重点):
此初始值设定项用于创建层的卷影副本,例如,用于presentationLayer方法在任何其他情况下使用此方法将产生未定义的行为。例如,不要使用此方法使用现有层的内容初始化新层。
因此,由于在这种情况下调用此初始化器的行为是未定义的,因此在您的情况下,它将返回nil
——然后在访问时强制展开,因为这是一个隐式展开的可选选项
您应该只使用init()
创建层。我还建议您内联定义层实例,并去掉隐式展开的选项,如图所示。例如:
class CircularProgressView: UIView {
let progressBackgroundLayer = CAShapeLayer()
let progressLayer = CAShapeLayer()
let iconLayer = CAShapeLayer()
...
func setup() {
layer.addSublayer(progressBackgroundLayer)
layer.addSublayer(progressLayer)
layer.addSublayer(iconLayer)
}
为了将图层添加到视图中,需要使用视图图层上的方法。例如:
class CircularProgressView: UIView {
let progressBackgroundLayer = CAShapeLayer()
let progressLayer = CAShapeLayer()
let iconLayer = CAShapeLayer()
...
func setup() {
layer.addSublayer(progressBackgroundLayer)
layer.addSublayer(progressLayer)
layer.addSublayer(iconLayer)
}
另外,drawRect:
用于绘制视图的内容,因此定义层的框架是完全错误的(仅当视图的边界更改时才会发生)。你应该考虑这样做。
最后,这段代码毫无意义:
convenience init() {
self.init(frame: CGRectZero)
}
这正是
UIView
实现init
所做的。您不应该使用init(layer:)
初始化器来创建CAShapeLayers
。(我的重点):
此初始值设定项用于创建层的卷影副本,例如,用于presentationLayer方法在任何其他情况下使用此方法将产生未定义的行为。例如,不要使用此方法使用现有层的内容初始化新层。
因此,由于在这种情况下调用此初始化器的行为是未定义的,因此在您的情况下,它将返回nil
——然后在访问时强制展开,因为这是一个隐式展开的可选选项
您应该只使用init()
创建层。我还建议您内联定义层实例,并去掉隐式展开的选项,如图所示。例如:
class CircularProgressView: UIView {
let progressBackgroundLayer = CAShapeLayer()
let progressLayer = CAShapeLayer()
let iconLayer = CAShapeLayer()
...
func setup() {
layer.addSublayer(progressBackgroundLayer)
layer.addSublayer(progressLayer)
layer.addSublayer(iconLayer)
}
为了将图层添加到视图中,需要使用视图图层上的方法。例如:
class CircularProgressView: UIView {
let progressBackgroundLayer = CAShapeLayer()
let progressLayer = CAShapeLayer()
let iconLayer = CAShapeLayer()
...
func setup() {
layer.addSublayer(progressBackgroundLayer)
layer.addSublayer(progressLayer)
layer.addSublayer(iconLayer)
}
另外,drawRect:
用于绘制视图的内容,因此定义层的框架是完全错误的(仅当视图的边界更改时才会发生)。你应该考虑这样做。
最后,这段代码毫无意义:
convenience init() {
self.init(frame: CGRectZero)
}
这正是
UIView
实现init
所做的。在setup()
中layer
从何而来?这就是为什么您应该避免隐式展开选项。layer
在setup()中从何而来
?另外,这就是为什么您应该避免隐式展开选项。