Lançando CGFloat para Flutuar em Swift

91

Preciso armazenar um valor como a Float, mas os dados de origem são CGFloat:

let myFloat : Float = myRect.origin.x

mas isso resulta no erro do compilador: 'NSNumber' não é do subtipo 'Float'

Então, se eu lançar explicitamente assim:

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

mas isso, por sua vez, resulta no erro do compilador: 'Não é possível converter o tipo da expressão' Float 'para' Float ''

Qual é a maneira correta de fazer isso e satisfazer o compilador, por favor?

Andrew Ebling
fonte
8
Esteja ciente de que em sistemas de 64 bits, a conversão de CGFloat em Float perde precisão - CGFloat é de 64 bits em sistemas de 64 bits e de 32 bits em sistemas de 32 bits, Float é sempre de 32 bits. Para evitar isso, você pode usar Double em vez de Float.
Lukas de
se você pesquisar em um CGFloat no Xcode e ver onde ele está definido, verá que ele é definido como um float na arquitetura de 32 bits e duplo na arquitetura de 64 bits.
jcpennypincher

Respostas:

173

Você pode usar o Float()inicializador:

let cgFloat: CGFloat = 3.14159
let someFloat = Float(cgFloat)
Erik
fonte
17
usar "float" como nome de variável é um pouco confuso, talvez a mudança seja para algo como "swFloat"?
Fermat's Little Student
2
"'flutuar' é um pouco confuso". Seriamente?
AlvinfromDiaspar
2
@AlvinfromDiaspar Sim, provavelmente porque outras linguagens usam em floatvez de Float, então parece esse tipo / palavra-chave em vez de um nome de variável.
Supuhstar
29

Se você for tão preguiçoso quanto eu, em Extensions.swift defina o seguinte:

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

Então você pode fazer:

var someCGFloatFromFloat = 1.3.f
var someCGFloatFromInt = 2.f
var someFloatFromCGFloat = someCGFloatFromFloat.swf
Hyouuu
fonte
1
parece um candidato a uma estrutura genérica
μολὼν.λαβέ
@Ian eu não entendo sua pergunta ... um exemplo?
hyouuu
13

Normalmente, a melhor solução é manter o tipo e o uso CGFloat, mesmo em Swift. Isso porque CGFloattem tamanhos diferentes em máquinas de 32 bits e 64 bits.

A palavra-chave aspode ser usada apenas para conversão dinâmica (para subclasses), por exemplo

class A {
}

class B : A {
}

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

No entanto, Double, Int, Floatetc não são subclasses do outro, portanto, "cast" você tem que criar uma nova instância, por exemplo,

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
fonte
Observe que você também pode usar aspara converter um tipo genérico em um tipo concreto. Por exemplo, se você tinha uma função que aceita um tipo genérico em conformidade com BinaryInteger, você pode convertê-la para Intusando as?ou as!.
Peter Schorn