I'm trying to draw some dashed lines on an app but it only draws on main.storyboard with IBDesignable. When I run the app on iOS simulator, nothing shows. What's happening?
The code to draw:
@IBDesignable
class AnalogView: UIView {
fileprivate let thickHorizontalLayer = CAShapeLayer()
fileprivate let thinHorizontalLayer = CAShapeLayer()
@IBInspectable var thickYCoord = 50.0
@IBInspectable var thinYCoord = 52.5
override init(frame: CGRect) {
super.init(frame: frame)
let thickDashesPath = UIBezierPath()
thickDashesPath.move(to: CGPoint(x: 0, y: thickYCoord)) //left
thickDashesPath.addLine(to: CGPoint(x: 340, y: thickYCoord)) //right
//thickHorizontalLayer.frame = frame
thickHorizontalLayer.path = thickDashesPath.cgPath
thickHorizontalLayer.strokeColor = UIColor.black.cgColor //dashes color
thickHorizontalLayer.lineWidth = 20
thickHorizontalLayer.lineDashPattern = [ 1, 83.5 ]
//thickHorizontalLayer.lineDashPhase = 0.25
self.layer.addSublayer(thickHorizontalLayer)
let thinDashesPath = UIBezierPath()
thinDashesPath.move(to: CGPoint(x: 0, y: thinYCoord)) //esquerda
thinDashesPath.addLine(to: CGPoint(x: 340, y: thinYCoord)) //direita
//thinHorizontalLayer.frame = frame
thinHorizontalLayer.path = thinDashesPath.cgPath
thinHorizontalLayer.strokeColor = UIColor.black.cgColor
thinHorizontalLayer.lineWidth = 15.0
thinHorizontalLayer.fillColor = UIColor.clear.cgColor
thinHorizontalLayer.lineDashPattern = [ 0.5, 7.95]
//thinHorizontalLayer.lineDashPhase = 0.25
self.layer.addSublayer(thinHorizontalLayer)
You need to put the common code in a routine that is called by both init(frame:)
and init(coder:)
:
@IBDesignable
class AnalogView: UIView {
fileprivate let thickHorizontalLayer = CAShapeLayer()
fileprivate let thinHorizontalLayer = CAShapeLayer()
@IBInspectable var thickYCoord: CGFloat = 50.0
@IBInspectable var thinYCoord: CGFloat = 52.5
override init(frame: CGRect = .zero) {
super.init(frame: frame)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
private func configure() {
let thickDashesPath = UIBezierPath()
thickDashesPath.move(to: CGPoint(x: 0, y: thickYCoord)) //left
thickDashesPath.addLine(to: CGPoint(x: 340, y: thickYCoord)) //right
thickHorizontalLayer.path = thickDashesPath.cgPath
thickHorizontalLayer.strokeColor = UIColor.black.cgColor //dashes color
thickHorizontalLayer.lineWidth = 20
thickHorizontalLayer.lineDashPattern = [ 1, 83.5 ]
self.layer.addSublayer(thickHorizontalLayer)
let thinDashesPath = UIBezierPath()
thinDashesPath.move(to: CGPoint(x: 0, y: thinYCoord)) //esquerda
thinDashesPath.addLine(to: CGPoint(x: 340, y: thinYCoord)) //direita
thinHorizontalLayer.path = thinDashesPath.cgPath
thinHorizontalLayer.strokeColor = UIColor.black.cgColor
thinHorizontalLayer.lineWidth = 15.0
thinHorizontalLayer.fillColor = UIColor.clear.cgColor
thinHorizontalLayer.lineDashPattern = [ 0.5, 7.95]
self.layer.addSublayer(thinHorizontalLayer)
}
}
I'd also suggest declaring an explicit type for your @IBInspectable
types, or else you won't be able to adjust them in IB.
Personally, rather than hard coding the path width, I'd update it when the layout changes. Also, if you're going to make those properties @IBDesignable
, you really want to update the paths if they change.
@IBDesignable
class AnalogView: UIView {
fileprivate let thickHorizontalLayer = CAShapeLayer()
fileprivate let thinHorizontalLayer = CAShapeLayer()
@IBInspectable var thickYCoord: CGFloat = 50.0 { didSet { updatePaths() } }
@IBInspectable var thinYCoord: CGFloat = 52.5 { didSet { updatePaths() } }
override init(frame: CGRect = .zero) {
super.init(frame: frame)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
private func configure() {
layer.addSublayer(thickHorizontalLayer)
layer.addSublayer(thinHorizontalLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
updatePaths()
}
private func updatePaths() {
let thickDashesPath = UIBezierPath()
thickDashesPath.move(to: CGPoint(x: bounds.origin.x, y: thickYCoord)) //left
thickDashesPath.addLine(to: CGPoint(x: bounds.origin.x + bounds.size.width, y: thickYCoord)) //right
thickHorizontalLayer.path = thickDashesPath.cgPath
thickHorizontalLayer.strokeColor = UIColor.black.cgColor //dashes color
thickHorizontalLayer.lineWidth = 20
thickHorizontalLayer.lineDashPattern = [1.0, NSNumber(value: Double(bounds.size.width - 1) / 4 - 1.0) ]
let thinDashesPath = UIBezierPath()
thinDashesPath.move(to: CGPoint(x: bounds.origin.x, y: thinYCoord)) //esquerda
thinDashesPath.addLine(to: CGPoint(x: bounds.origin.x + bounds.size.width, y: thinYCoord)) //direita
thinHorizontalLayer.path = thinDashesPath.cgPath
thinHorizontalLayer.strokeColor = UIColor.black.cgColor
thinHorizontalLayer.lineWidth = 15.0
thinHorizontalLayer.fillColor = UIColor.clear.cgColor
thinHorizontalLayer.lineDashPattern = [0.5, NSNumber(value: Double(bounds.size.width - 1) / 40 - 0.5)]
}
}
You might want to adjust the dashing to span the width, too (I'm not sure if you wanted a consistent scale or for it to span the width). But hopefully this illustrates the idea.