Why the below code throws fatal error: unexpectedly found nil while unwrapping an Optional value when run in Xcode playground? I am not sure what is wrong with the below code. Thanks for your help. I haven't tried running it outside playground.
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
You shouldn't use the
init(layer:)initialiser in order to create yourCAShapeLayers. From the documentation (emphasis mine):Therefore, as the behaviour of calling this initialiser is undefined in this circumstance, it's returning
nilin your case – which you're then force unwrapping upon accessing, as it's an implicitly unwrapped optional.You should instead just create your layers with
init(). I would also recommend that you define your layer instances inline, and get rid of the implicitly unwrapped optionals, as they're inherently unsafe. For example:In order to add the layers to your view, you need to use the
addSublayer:method on the view's layer. For example:Also,
drawRect:is used to draw the contents of your view, and therefore is totally the wrong place to be defining the frames of your layers (which should only occur when the view's bounds changes). You should instead consider doing this inlayoutSubviews.And finally, this code is pointless:
This is exactly what the
UIViewimplementation ofinitdoes already.