0

fatal error: unexpectedly found nil while unwrapping an Optional value为什么在 Xcode 游乐场运行时会抛出以下代码?我不确定下面的代码有什么问题。谢谢你的帮助。我还没有尝试在操场外运行它。

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
4

1 回答 1

2

您不应该使用init(layer:)初始化程序来创建您的CAShapeLayers. 从文档(强调我的):

此初始化程序用于创建图层的影子副本,例如,用于presentationLayer 方法。在任何其他情况下使用此方法将产生未定义的行为。例如,不要使用此方法用现有图层的内容初始化新图层。

因此,由于在这种情况下调用此初始化程序的行为是未定义的,它会nil在您的情况下返回 - 然后您在访问时强制解包,因为它是一个隐式解包的可选项。

相反,您应该只使用init(). 我还建议您内联定义您的图层实例,并摆脱隐式展开的选项,因为它们本质上是 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已经做的事情。

于 2016-05-11T16:23:56.767 回答