0

fatal error: unexpectedly found nil while unwrapping an Optional valueXcode プレイグラウンドで実行すると、以下のコードがスローされるのはなぜですか? 以下のコードの何が問題なのかわかりません。ご協力いただきありがとうございます。遊び場の外で実行しようとはしていません。

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 に答える