Przesyłanie CGFloat do Float w Swift

93

Muszę zapisać wartość jako a Float, ale dane źródłowe to CGFloat:

let myFloat : Float = myRect.origin.x

ale skutkuje to błędem kompilatora: „NSNumber” nie jest podtypu „Float”

Więc jeśli wyraźnie rzucę to w ten sposób:

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

ale to z kolei powoduje błąd kompilatora: „Nie można przekonwertować typu wyrażenia„ Float ”na„ Float ””

Jaki jest właściwy sposób, aby to zrobić i zadowolić kompilatora?

Andrew Ebling
źródło
9
Należy pamiętać, że w systemach 64-bitowych rzutowanie CGFloat na Float traci precyzję - CGFloat to 64 bity w systemach 64-bitowych i 32 bity w systemie 32-bitowym, Float ma zawsze 32 bity. Aby tego uniknąć, możesz użyć Double zamiast Float.
Lukas
jeśli przeanalizujesz CGFloat w Xcode i zobaczysz, gdzie jest zdefiniowany, zobaczysz, że jest on wpisany jako zmiennoprzecinkowy w architekturze 32-bitowej i podwójny w architekturze 64-bitowej.
jcpennypincher

Odpowiedzi:

176

Możesz użyć Float()inicjatora:

let cgFloat: CGFloat = 3.14159
let someFloat = Float(cgFloat)
Erik
źródło
17
używanie „float” jako nazwy zmiennej jest nieco mylące, być może zmiana na coś takiego jak „swFloat”?
Mały uczeń Fermata,
2
„'float' jest nieco mylące”. Poważnie?
AlvinfromDiaspar
2
@AlvinfromDiaspar Tak, prawdopodobnie ponieważ inne języki używają floatzamiast Float, więc zamiast nazwy zmiennej wygląda to jak ten typ / słowo kluczowe.
Supuhstar
29

Jeśli jesteś tak leniwy jak ja, w Extensions.swift zdefiniuj następujące elementy:

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) }
}

Następnie możesz:

var someCGFloatFromFloat = 1.3.f
var someCGFloatFromInt = 2.f
var someFloatFromCGFloat = someCGFloatFromFloat.swf
hyouuu
źródło
1
wygląda jak kandydat do struktury generycznej
μολὼν.λαβέ
@Ian, nie rozumiem twojego pytania ... przykład?
hyouuu
13

Zwykle najlepszym rozwiązaniem jest zachowanie typu i użycia CGFloat, nawet w Swift. To dlatego, że CGFloatma inny rozmiar na komputerach 32-bitowych i 64-bitowych.

Słowo kluczowe asmoże być używane tylko do rzutowania dynamicznego (dla podklas), np

class A {
}

class B : A {
}

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

Jednak Double, Int, Floatetc nie są podklasy siebie, więc do „obsady” trzeba utworzyć nową instancję, np

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
Sulthan
źródło
Zauważ, że możesz również użyć asdo rzutowania typu ogólnego na typ konkretny. Na przykład, jeśli masz funkcję, która akceptuje typ ogólny, który jest zgodny z BinaryInteger, możesz rzutować ją na Intużycie as?lub as!.
Peter Schorn