Trying to do arithmetic in a function that returns `CGFloat, I get an error:
Couldn't find overload for '/' that accepts supplied arguments
func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
{
return (M_PI * (x) / 180.0) // error is here.
}
Has anyone else seen this type of issue?
This is a problem with double
to float
conversion.
On a 64-bit machine, CGFloat
is defined as double
and you will compile it without problems because M_PI
and x
are both doubles.
On a 32-bit machine, CGFloat
is a float
but M_PI
is still a double. Unfortunately, there are no implicit casts in Swift, so you have to cast explicitly:
return (CGFloat(M_PI) * (x) / 180.0)
The type for 180.0
literal is inferred.
In Swift 3
M_PI
is deprecated, use CGFloat.pi
instead:
return (x * .pi / 180.0)
In this specific case I have a cute trick to recommend
let π = CGFloat(M_PI)
Unicode everywhere, and π is easy to get to with Opt+P
Its best to abstract away the complexity. First create an extension
extension Double {
/** Converts the specified value in degrees into radians. */
func degrees() -> CGFloat {
return CGFloat(self) * CGFloat(M_PI / 180.0)
}
}
then use it in your code such as the following example
let angle = 30.0.degrees()
let transform = CGAffineTransformRotate(self.sliderControl.transform, angle);
At first I was reluctant to extend Double because I don't like creating a custom tailored use of the language (from coding horrors found in C++). However, practical experience has shown this to being a way of abstraction natural to the language.
This should fix the error:
func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
{
return (CGFloat(M_PI) * (x) / 180.0)
}
The reason the error is occurring is because x
is explicitly declared to be a CGFloat
, while M_PI
has the type CDouble
, as seen in the declaration:
var M_PI: CDouble { get } /* pi */
Because of this, you need to cast M_PI
to type CGFloat
so it matches the type of x
(as I have done in the code above). This way, there is no conflict in operating on different types.
Note that, contrary to what is stated in other answers (and as @Cezar commented), you do not need to explicitly cast 180.0
to the CGFloat
type, because it is a literal, and does not have an explicit type, so will automatically be converted to CGFloat
without needing a manual cast.