หล่อ CGFloat เพื่อลอยใน Swift


94

ฉันต้องการเก็บค่าเป็น a Floatแต่แหล่งข้อมูลคือCGFloat:

let myFloat : Float = myRect.origin.x

แต่ผลลัพธ์นี้ทำให้เกิดข้อผิดพลาดของคอมไพเลอร์: 'NSNumber' ไม่ใช่ประเภทย่อย 'Float'

ดังนั้นถ้าฉันโยนมันอย่างชัดเจนเช่นนี้:

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

แต่สิ่งนี้ทำให้เกิดข้อผิดพลาดของคอมไพเลอร์: 'ไม่สามารถแปลงประเภทของนิพจน์' Float 'เป็น' Float ''

อะไรคือวิธีที่ถูกต้องในการดำเนินการและตอบสนองความต้องการของคอมไพเลอร์?


9
โปรดทราบว่าในระบบ 64 บิตการหล่อ CGFloat เป็น Float จะสูญเสียความแม่นยำ - CGFloat คือ 64 บิตในระบบ 64 บิตและ 32 บิตในระบบ 32 บิต Float เป็น 32 บิตเสมอ เพื่อหลีกเลี่ยงปัญหานี้คุณสามารถใช้ Double แทน Float
Lukas


หากคุณเจาะลึก CGFloat ใน Xcode และดูว่ามีการกำหนดไว้ที่ใดคุณจะเห็นว่ามันถูก typedef เป็นลอยบนสถาปัตยกรรม 32 บิตและสถาปัตยกรรม 64 บิตสองเท่า
jcpennypincher

คำตอบ:


176

คุณสามารถใช้ตัวFloat()เริ่มต้น:

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

17
การใช้ "float" เป็นชื่อตัวแปรนั้นค่อนข้างสับสนบางทีอาจเปลี่ยนเป็น "swFloat"?
Fermat's Little Student

2
"ลอย" ค่อนข้างสับสน " อย่างจริงจัง?
AlvinfromDiaspar

2
@AlvinfromDiaspar ใช่น่าจะเป็นเพราะภาษาอื่นใช้floatแทนFloatดังนั้นจึงดูเหมือนว่าประเภท / คำหลักนั้นแทนที่จะเป็นชื่อตัวแปร
Supuhstar

29

หากคุณขี้เกียจเหมือนฉันใน Extensions.swift กำหนดสิ่งต่อไปนี้:

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

จากนั้นคุณสามารถทำได้:

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

1
ดูเหมือนผู้สมัครสำหรับโครงสร้างทั่วไป
μολὼν.λαβέ

@ Ian ฉันไม่เข้าใจคำถามของคุณ ... ตัวอย่าง?
hyouuu

13

โดยปกติทางออกที่ดีที่สุดคือรักษาประเภทและการใช้งานCGFloatไว้แม้ใน Swift นั่นเป็นเพราะCGFloatมีขนาดที่แตกต่างกันในเครื่อง 32 บิตและ 64 บิต

asสามารถใช้คีย์เวิร์ดสำหรับการแคสต์แบบไดนามิกเท่านั้น (สำหรับคลาสย่อย) เช่น

class A {
}

class B : A {
}

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

อย่างไรก็ตามDouble, Int, Floatฯลฯ ไม่ได้คลาสย่อยของแต่ละอื่น ๆ จึงจะ "โยน" คุณต้องสร้างตัวอย่างใหม่เช่น

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

โปรดทราบว่าคุณสามารถใช้asสำหรับการหล่อประเภททั่วไปเป็นประเภทคอนกรีตได้ ตัวอย่างเช่นถ้าคุณมีฟังก์ชั่นที่ยอมรับชนิดทั่วไปที่สอดคล้องกับBinaryIntegerคุณสามารถโยนมันทิ้งไปIntใช้หรือas? as!
Peter Schorn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.