Casting CGFloat to Float in Swift
Asked Answered
C

3

104

I need to store a value as a Float, but the source data is a CGFloat:

let myFloat : Float = myRect.origin.x

but this results in the compiler error: 'NSNumber' is not of subtype 'Float'

So if I explicitly cast it like this:

let myFloat : Float = myRect.origin.x as Float

but this in turn results in the compiler error: 'Cannot convert the expression's type 'Float' to 'Float''

What's the correct way to do this and satisfy the compiler please?

Cryan answered 10/6, 2014 at 17:42 Comment(3)
Be aware that on 64-bit systems, casting CGFloat to Float loses precision – CGFloat is 64 bits on 64-bit systems and 32 bits on 32-bit system, Float is always 32 bits. To avoid this, you could use Double instead of Float.Mongrelize
possible duplicate of swift : Confusion due to no implicit conversion of CGFloatLimekiln
if you drill down on a CGFloat in Xcode and see where it is defined you will see that it is typedef'd as a float on 32 bit architecture and a double on 64 bit architecture.Leede
F
199

You can use the Float() initializer:

let cgFloat: CGFloat = 3.14159
let someFloat = Float(cgFloat)
Fibre answered 10/6, 2014 at 17:47 Comment(3)
using "float" as variable name is somewhat confusing, perhaps change is to something like "swFloat"?Elsy
" 'float' is somewhat confusing". Seriously?Tertias
@Tertias Yes, likely since other languages use float instead of Float, so it looks like that type/keyword instead of a variable name.Zollverein
F
34

If you are as lazy as I am, in an Extensions.swift define the following:

extension Int {
  var f: CGFloat { return CGFloat(self) }
}

extension Float {
  var f: CGFloat { return CGFloat(self) }
}

extension Double {
  var f: CGFloat { return CGFloat(self) }
}

extension CGFloat {
  var swf: Float { return Float(self) }
}

Then you can do:

var someCGFloatFromFloat = 1.3.f
var someCGFloatFromInt = 2.f
var someFloatFromCGFloat = someCGFloatFromFloat.swf
Frierson answered 9/11, 2014 at 16:47 Comment(2)
looks like a candidate for generic structRollin
@Ian I don't understand your question... an example?Frierson
L
13

Usually, the best solution is to keep the type and use CGFloat, even in Swift. That's because CGFloat has different size on 32bit and 64bit machines.

Keyword as can be used only for dynamic casting (for subclasses), e.g.

class A {
}

class B : A {
}

var a: A = B()
var b: B = a as B

However, Double, Int, Float etc are not subclasses of each other, therefore to "cast" you have to create a new instance, e.g.

var d: Double = 2.0
var f: Float = Float(d) //this is an initialiser call, not a cast
var i: Int = Int(d) //this is an initialiser call, not a cast
Limekiln answered 10/6, 2014 at 18:4 Comment(1)
Note that you can also use as for casting a generic type into a concrete type. For example, if you had a function that accepts a generic type that conforms to BinaryInteger, you can cast it to Int using as? or as!.Disassemble

© 2022 - 2024 — McMap. All rights reserved.