As we all know, CGFloat (which is ubiquitous in CoreGraphics, UIKit etc)
can be a 32-bit or 64-bit floating point number, depending on the
processor architecture.
In C, CGFloat it is a typealias
to float or double, in Swift is it defined as a struct CGFloat with
a native property (which is Float or Double).
It has been observed repeatedly that a NSNumber can be created from
and converted to Float and Double, but that there exist not
similar conversions from and to CGFloat. The general advice
(e.g. in Convert CGFloat to NSNumber in Swift) is to
convert via Double
CGFloat <--> Double <--> NSNumber
Example:
let c1 = CGFloat(12.3)
let num = NSNumber(double: Double(c1))
let c2 = CGFloat(num.doubleValue)
and that is simple and correct, no precision is lost.
Also most platforms are 64-bit nowadays, and then the CGFloat/Double
conversion is trivial and probably optimized by the compiler.
However, it aroused my curiosity if a conversion can be done
without promoting CGFloat to Double on 32-bit platforms.
One could use a build configuration statement (as e.g. in Should conditional compilation be used to cope with difference in CGFloat on different architectures?):
extension NSNumber {
convenience init(cgFloatValue value : CGFloat) {
#if arch(x86_64) || arch(arm64)
self.init(double: value.native)
#else
self.init(float: value.native)
#endif
}
}
But what if Swift is ported to other architectures which are not Intel or ARM? This does not look very future proof.
One could also use the CGFLOAT_IS_DOUBLE constant (as e.g. in
NSNumber from CGFloat):
if CGFLOAT_IS_DOUBLE != 0 {
// ...
} else {
// ...
}
The disadvantage here is that the compiler will always emit a "Will never be executed" warning on one of the cases.
So to make the long story short:
- How can we convert between
CGFloatandNSNumberin a safe way, without compiler warnings, and without unnecessary promotion toDouble?
Please note that this is meant as an "academic" problem. As mentioned
above (and in other Q&A's) one can simply convert via Double
practically.
I am posting a "self-answer" here in the spirit of share your knowledge, Q&A-style. Of course other answers are welcome!