Mentransmisikan CGFloat ke Float di Swift

94

Saya perlu menyimpan nilai sebagai Float, tetapi sumber datanya adalah CGFloat:

let myFloat : Float = myRect.origin.x

tetapi ini menghasilkan kesalahan penyusun: 'NSNumber' bukan subtipe 'Float'

Jadi jika saya secara eksplisit menampilkannya seperti ini:

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

tetapi ini pada gilirannya menghasilkan kesalahan penyusun: 'Tidak dapat mengubah jenis ekspresi' Float 'menjadi' Float ''

Apa cara yang benar untuk melakukan ini dan memuaskan kompilator?

Andrew Ebling
sumber
9
Ketahuilah bahwa pada sistem 64-bit, mentransmisikan CGFloat ke Float kehilangan presisi - CGFloat adalah 64 bit pada sistem 64-bit dan 32 bit pada sistem 32-bit, Float selalu 32 bit. Untuk menghindarinya, Anda bisa menggunakan Double sebagai pengganti Float.
Lukas
jika Anda menelusuri CGFloat di Xcode dan melihat di mana ia didefinisikan, Anda akan melihat bahwa itu diketik sebagai float pada arsitektur 32 bit dan ganda pada arsitektur 64 bit.
jcpennypincher

Jawaban:

176

Anda dapat menggunakan Float()penginisialisasi:

let cgFloat: CGFloat = 3.14159
let someFloat = Float(cgFloat)
Erik
sumber
17
menggunakan "float" sebagai nama variabel agak membingungkan, mungkin perubahannya menjadi seperti "swFloat"?
Siswa Kecil Fermat
2
"'float' agak membingungkan". Sungguh?
AlvinfromDiaspar
2
@AlvinfromDiaspar Ya, mungkin karena bahasa lain menggunakan floatalih-alih Float, jadi sepertinya jenis / kata kunci itu bukan nama variabel.
Supuhstar
29

Jika Anda malas seperti saya, dalam Extensions.swift tentukan yang berikut:

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

Kemudian Anda dapat melakukan:

var someCGFloatFromFloat = 1.3.f
var someCGFloatFromInt = 2.f
var someFloatFromCGFloat = someCGFloatFromFloat.swf
hyouuu
sumber
1
Sepertinya kandidat untuk struct generik
μολὼν.λαβέ
@Ian saya tidak mengerti pertanyaan Anda ... sebuah contoh?
hyouuu
13

Biasanya, solusi terbaik adalah mempertahankan jenis dan penggunaannya CGFloat, bahkan di Swift. Itu karena CGFloatmemiliki ukuran yang berbeda pada mesin 32bit dan 64bit.

Kata kunci hanya asdapat digunakan untuk casting dinamis (untuk subclass), mis

class A {
}

class B : A {
}

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

Namun, Double, Int, Floatdll tidak subclass satu sama lain, oleh karena itu untuk "pemain" Anda harus membuat contoh baru, misalnya

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
sumber
Perhatikan bahwa Anda juga dapat menggunakan asuntuk menuang tipe generik menjadi tipe beton. Misalnya, jika Anda memiliki fungsi yang menerima tipe generik yang sesuai BinaryInteger, Anda dapat mentransmisikannya ke Intmenggunakan as?atau as!.
Peter Schorn