Reputation: 131
I have this simple example where I try to draw a circle. This code below does not give me a circle.
import UIKit
class PlayingCardView: UIView {
override func draw(_ rect: CGRect) {
if let context = UIGraphicsGetCurrentContext(){
context.addArc(center: CGPoint(x: bounds.midX,
y: bounds.midY), radius: 100.0,
startAngle: 0,
endAngle: CGFloat(2.0*Float.pi),
clockwise: true)
context.setLineWidth(5.0)
UIColor.red.setStroke()
context.strokePath()
print(2.0*CGFloat.pi)
print(CGFloat(2.0*Float.pi))
}
}
}
This is what I get with the above code:
with output:
6.283185307179586
6.283185005187988
from the print statements which correspond to 2.0*CGFloat.pi
and CGFloat(2.0*Float.pi)
respectively.
Updating the code to this (I only change the endAngle in context.addArc
to be 2.0*CGFloat.pi
instead of CGFloat(2.0*Float.pi)
import UIKit
class PlayingCardView: UIView {
override func draw(_ rect: CGRect) {
if let context = UIGraphicsGetCurrentContext(){
context.addArc(center: CGPoint(x: bounds.midX,
y: bounds.midY), radius: 100.0,
startAngle: 0,
endAngle: 2.0*CGFloat.pi,
clockwise: true)
context.setLineWidth(5.0)
UIColor.red.setStroke()
context.strokePath()
print(2.0*CGFloat.pi)
print(CGFloat(2.0*Float.pi))
}
}
}
I get this drawing (The circle is there)
There is obviously a difference between the casted CGFloat from Float and CGFloat. Does anybody know what it is and why this behavior is useful in Swift?
Upvotes: 2
Views: 72
Reputation: 540055
On a 64-bit platform, CGFloat
is (essentially) Double
, a 64-bit floating point number, whereas Float
is a 32-bit floating point number.
So 2.0*Float.pi
is “2π with 32-bit precision”, and converting that to the 64-bit quantity CGFloat
preserves the value, without increasing the precision.
That is why 2.0*CGFloat.pi != CGFloat(2.0*Float.pi)
. The former is “2π with 64-bit precision”, and is what you should pass to the drawing functions.
In your particular case, CGFloat(2.0*Float.pi)
is a tiny bit smaller than 2.0*CGFloat.pi
, so that only an invisibly short arc is drawn (from radians 0.0 to approximately -0.00000003).
For a full circle you can alternatively use
let radius: CGFloat = 100.0
context.addEllipse(in: CGRect(x: bounds.midX - radius, y: bounds.midY - radius,
width: 2.0 * radius, height: 2.0 * radius))
and avoid all rounding problems.
Upvotes: 3