Reputation: 229
In Swift 4, with the Xcode IDE, I can easily draw a circle with the following:
let circlePath = UIBezierPath(arcCenter: CGPoint(
x: 100,
y: 100),
radius: 50,
startAngle: CGFloat(0),
endAngle:CGFloat(Double.pi * 2),
clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.strokeColor = UIColor.black.cgColor
shapeLayer.lineWidth = 2.0
However, I want to draw a line from point A to point B, not draw a circle. I can draw a line by following the example code here: https://www.youtube.com/watch?v=9sJxtzTo8W0
In order for the line to appear the same way that it does in the example, I need to change the view in the main storyboard.
Does this mean that I can only have 1 type of custom class in my entire project that is viewable at any given time?
Can I make the lines viewable by default, regardless of the specific storyboard view?
Why does the circle render without me needing to define a class object, but the line requires me to define a class object?
Is there a way to simply draw a line on the fly, in the same way that I can draw a circle on the fly?
Upvotes: 3
Views: 2091
Reputation: 438232
Is there a way to simply draw a line on the fly, in the same way that I can draw a circle on the fly?
Sure, just create a UIBezierPath
with addLine(to:)
and then use the following path
in your CAShapeLayer
, just like you did for the circle in your example:
let startPoint = CGPoint(x: 10, y: 10)
let endPoint = CGPoint(x: 20, y: 5)
let linePath = UIBezierPath()
linePath.move(to: startPoint)
linePath.addLine(to: endPoint)
let shapeLayer = CAShapeLayer()
shapeLayer.path = linePath.cgPath
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.strokeColor = UIColor.black.cgColor
shapeLayer.lineWidth = 2
view.layer.addSublayer(shapeLayer)
Why does the circle render without me needing to define a class object, but the line requires me to define a class object?
The line doesn’t require you to define class object. It’s just another way of doing it and you can do both lines and circles (and whatever other types of shapes you want) using either the CAShapeLayer
technique or the UIView
subclass technique. They both work fine.
A UIView
subclass approach, you first define your class:
class LineView: UIView {
var startPoint: CGPoint? { didSet { setNeedsDisplay() } }
var endPoint: CGPoint? { didSet { setNeedsDisplay() } }
override func draw(_ rect: CGRect) {
guard let startPoint = startPoint, let endPoint = endPoint else { return }
let linePath = UIBezierPath()
linePath.move(to: startPoint)
linePath.addLine(to: endPoint)
linePath.lineWidth = 2
UIColor.black.setStroke()
linePath.stroke()
}
}
And then instantiate one and add it to your view hierarchy:
let lineView = LineView()
lineView.backgroundColor = .lightGray
lineView.translatesAutoresizingMaskIntoConstraints = false
lineView.startPoint = CGPoint(x: 10, y: 10)
lineView.endPoint = CGPoint(x: 20, y: 5)
view.addSubview(lineView)
NSLayoutConstraint.activate([
lineView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
lineView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
lineView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10),
lineView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10)
])
Does this mean that I can only have 1 type of custom class in my entire project that is viewable at any given time?
Just like you can add whatever shapelayers you want, you can add your own custom UIView
subclasses and add however many you want. So you could theoretically have a couple of subclass types, one for different types of shapes (circles, lines, rounded rectangles, whatever) and instantiate them and add them as subviews to whatever view on whatever scene you wanted.
Upvotes: 2