Преобразование CGFloat в Float в 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.
Лукас


если вы углубитесь в CGFloat в Xcode и посмотрите, где он определен, вы увидите, что он определен как float в 32-битной архитектуре и как double в 64-битной архитектуре.
jcpennypincher

Ответы:


176

Вы можете использовать Float()инициализатор:

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

17
использование «float» в качестве имени переменной несколько сбивает с толку, возможно, нужно изменить что-то вроде «swFloat»?
Маленькая ученица Ферма

2
«'float' несколько сбивает с толку». Шутки в сторону?
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
выглядит как кандидат на общую структуру
μολὼν.λαβέ 09

@ Ян, я не понимаю твоего вопроса ... пример?
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!.
Питер Шорн,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.