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
CGFloat
andNSNumber
in 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!