Casting CGFloat per fluttuare in Swift


91

Devo memorizzare un valore come a Float, ma i dati di origine sono CGFloat:

let myFloat : Float = myRect.origin.x

ma questo si traduce nell'errore del compilatore: "NSNumber" non è del sottotipo "Float"

Quindi, se lo lancio esplicitamente in questo modo:

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

ma questo a sua volta si traduce nell'errore del compilatore: 'Impossibile convertire il tipo di espressione' Float 'in' Float ''

Qual è il modo corretto per farlo e soddisfare il compilatore, per favore?


8
Tieni presente che su sistemi a 64 bit, la trasmissione di CGFloat a Float perde precisione: CGFloat è a 64 bit su sistemi a 64 bit e 32 bit su sistema a 32 bit, Float è sempre a 32 bit. Per evitare ciò, potresti usare Double invece di Float.
Lukas


se esegui il drill down su un CGFloat in Xcode e vedi dove è definito, vedrai che è typedef'd come float su architettura a 32 bit e double su architettura a 64 bit.
jcpennypincher

Risposte:


173

Puoi usare l' Float()inizializzatore:

let cgFloat: CGFloat = 3.14159
let someFloat = Float(cgFloat)

17
usare "float" come nome della variabile è un po 'confuso, forse il cambiamento è qualcosa come "swFloat"?
Fermat's Little Student

2
"'float' è un po 'confuso". Sul serio?
Alvin da Diaspar

2
@AlvinfromDiaspar Sì, probabilmente poiché altre lingue usano floatinvece di Float, quindi sembra quel tipo / parola chiave invece del nome di una variabile.
Supuhstar

29

Se sei pigro come me, in Extensions.swift definisci quanto segue:

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

Quindi puoi fare:

var someCGFloatFromFloat = 1.3.f
var someCGFloatFromInt = 2.f
var someFloatFromCGFloat = someCGFloatFromFloat.swf

1
sembra un candidato per la struttura generica
μολὼν.λαβέ

@Ian Non capisco la tua domanda ... un esempio?
hyouuu

13

Di solito, la soluzione migliore è mantenere il tipo e l'utilizzo CGFloat, anche in Swift. Questo perché CGFloatha dimensioni diverse su macchine a 32 bit e 64 bit.

La parola chiave aspuò essere utilizzata solo per il casting dinamico (per sottoclassi), ad es

class A {
}

class B : A {
}

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

Tuttavia, Double, Int, Floatecc non sono sottoclassi di ogni altro, quindi, a "cast" è necessario creare una nuova istanza, ad esempio,

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

Nota che puoi anche usare asper lanciare un tipo generico in un tipo concreto. Ad esempio, se hai una funzione che accetta un tipo generico conforme a BinaryInteger, puoi eseguirne il cast Intutilizzando as?o as!.
Peter Schorn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.