Lancer CGFloat pour flotter dans Swift

91

J'ai besoin de stocker une valeur en tant que Float, mais les données source sont CGFloat:

let myFloat : Float = myRect.origin.x

mais cela entraîne l'erreur du compilateur: 'NSNumber' n'est pas du sous-type 'Float'

Donc, si je le lance explicitement comme ceci:

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

mais cela entraîne à son tour l'erreur du compilateur: 'Impossible de convertir le type d'expression' Float 'en' Float ''

Quelle est la bonne façon de faire cela et de satisfaire le compilateur s'il vous plaît?

Andrew Ebling
la source
8
Sachez que sur les systèmes 64 bits, la conversion de CGFloat en Float perd en précision - CGFloat est 64 bits sur les systèmes 64 bits et 32 ​​bits sur les systèmes 32 bits, Float est toujours 32 bits. Pour éviter cela, vous pouvez utiliser Double au lieu de Float.
Lukas
Si vous explorez un CGFloat dans Xcode et voyez où il est défini, vous verrez qu'il est typé comme un flottant sur l'architecture 32 bits et un double sur l'architecture 64 bits.
jcpennypincher

Réponses:

173

Vous pouvez utiliser l' Float()initialiseur:

let cgFloat: CGFloat = 3.14159
let someFloat = Float(cgFloat)
Erik
la source
17
utiliser "float" comme nom de variable est quelque peu déroutant, peut-être que le changement est quelque chose comme "swFloat"?
Fermat's Little Student
2
"'float' est quelque peu déroutant". Sérieusement?
AlvinfromDiaspar
2
@AlvinfromDiaspar Oui, probablement puisque d'autres langues utilisent à la floatplace de Float, donc cela ressemble à ce type / mot-clé au lieu d'un nom de variable.
Supuhstar
29

Si vous êtes aussi paresseux que moi, dans un Extensions.swift définissez ce qui suit:

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

Ensuite, vous pouvez faire:

var someCGFloatFromFloat = 1.3.f
var someCGFloatFromInt = 2.f
var someFloatFromCGFloat = someCGFloatFromFloat.swf
hyouuu
la source
1
ressemble à un candidat pour une structure générique
μολὼν.λαβέ
@Je ne comprends pas votre question ... un exemple?
hyouuu
13

Habituellement, la meilleure solution est de conserver le type et l'utilisation CGFloat, même dans Swift. C'est parce qu'il CGFloata une taille différente sur les machines 32 bits et 64 bits.

Le mot-clé asne peut être utilisé que pour la diffusion dynamique (pour les sous-classes), par exemple

class A {
}

class B : A {
}

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

Cependant, Double, Int,Float etc sont les sous - classes non de l'autre, donc « cast » vous devez créer une nouvelle instance, par exemple

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
la source
Notez que vous pouvez également utiliser aspour convertir un type générique en un type concret. Par exemple, si vous aviez une fonction qui accepte un type générique conforme à BinaryInteger, vous pouvez la convertir en Intutilisant as?ou as!.
Peter Schorn