Преобразование CGFloat в Float в Swift

Мне нужно сохранить значение как Float, но исходные данные - это CGFloat:

let myFloat : Float = myRect.origin.x

но это приводит к ошибке компилятора: 'NSNumber' не относится к подтипу 'Float'

Итак, если я явно приведу его так:

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

но это, в свою очередь, приводит к ошибке компилятора: «Невозможно преобразовать тип выражения« Float »в« Float ».

Как правильно это сделать и удовлетворить компилятор?


person Andrew Ebling    schedule 10.06.2014    source источник
comment
Имейте в виду, что в 64-битных системах преобразование CGFloat в Float теряет точность - CGFloat является 64-битным в 64-битных системах и 32-битным в 32-битной системе, Float всегда 32-битный. Чтобы избежать этого, вы можете использовать Double вместо Float.   -  person Lukas    schedule 10.06.2014
comment
если вы углубитесь в CGFloat в Xcode и посмотрите, где он определен, вы увидите, что он определен по типу как float в 32-битной архитектуре и как double в 64-битной архитектуре.   -  person jcpennypincher    schedule 24.11.2014


Ответы (3)


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

let cgFloat: CGFloat = 3.14159
let someFloat = Float(cgFloat)
person Erik    schedule 10.06.2014
comment
использование float в качестве имени переменной несколько сбивает с толку, возможно, нужно изменить что-то вроде swFloat? - person Fermat's Little Student; 24.07.2014
comment
"float" несколько сбивает с толку. Шутки в сторону? - person AlvinfromDiaspar; 16.09.2016
comment
@AlvinfromDiaspar Да, скорее всего, поскольку в других языках используется float вместо Float, поэтому это похоже на этот тип / ключевое слово вместо имени переменной. - person Ky Leggiero; 11.03.2017

Если вы такой же ленивый, как и я, в 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
person hyouuu    schedule 09.11.2014
comment
выглядит как кандидат на универсальную структуру - person μολὼν.λαβέ; 09.03.2017
comment
@ Ян, я не понимаю твоего вопроса ... пример? - person hyouuu; 04.04.2017

Обычно лучшим решением является сохранение типа и использование 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
person Sulthan    schedule 10.06.2014
comment
Обратите внимание, что вы также можете использовать as для преобразования универсального типа в конкретный. Например, если у вас есть функция, которая принимает общий тип, соответствующий BinaryInteger, вы можете привести ее к Int, используя as? или as!. - person Peter Schorn; 06.08.2020