【问题标题】:Casting CGFloat to Float in Swift在 Swift 中将 CGFloat 转换为 Float
【发布时间】:2014-07-31 14:30:05
【问题描述】:

我需要将值存储为Float,但源数据是CGFloat

let myFloat : Float = myRect.origin.x

但这会导致编译器错误:“NSNumber”不是子类型“Float”

所以如果我像这样明确地转换它:

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

但这反过来会导致编译器错误:'Cannot convert the expression's type 'Float' to 'Float''

请问,这样做并满足编译器的正确方法是什么?

【问题讨论】:

  • 请注意,在 64 位系统上,将 CGFloat 转换为 Float 会丢失精度 - CGFloat 在 64 位系统上为 64 位,在 32 位系统上为 32 位,Float 始终为 32 位。为避免这种情况,您可以使用 Double 而不是 Float。
  • 如果您在 Xcode 中深入研究 CGFloat 并查看它的定义位置,您会看到它在 32 位架构上被 typedef 为浮点数,在 64 位架构上被定义为双精度。

标签: casting swift cgfloat


【解决方案1】:

如果你和我一样懒惰,请在 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

【讨论】:

  • 看起来像是通用结构的候选者
  • @Ian 我不明白你的问题...举个例子?
【解决方案2】:

您可以使用Float() 初始化器:

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

【讨论】:

  • 使用“float”作为变量名有点令人困惑,也许更改为“swFloat”之类的东西?
  • "'float' 有点令人困惑"。认真的吗?
  • @AlvinfromDiaspar 是的,可能因为其他语言使用float 而不是Float,所以它看起来像那个类型/关键字而不是变量名。
【解决方案3】:

通常,最好的解决方案是保留类型并使用 CGFloat,即使在 Swift 中也是如此。那是因为CGFloat 在 32 位和 64 位机器上的大小不同。

关键字as只能用于动态转换(用于子类),例如

class A {
}

class B : A {
}

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

但是,DoubleIntFloat 等不是彼此的子类,因此要“强制转换”,您必须创建一个新实例,例如

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 的泛型类型,则可以使用 as?as! 将其强制转换为 Int
猜你喜欢
  • 2018-10-12
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
  • 2014-07-24
  • 1970-01-01
相关资源
最近更新 更多