可以是32位或64位浮点数,具体取决于
处理器架构.
在C,CGFloat中它是一种类型
浮点数或双精度数,在Swift中定义为带有的结构CGFloat
本地属性(Float或Double).
已经反复观察到可以从中创建NSNumber
并转换为Float和Double,但不存在
来自CGFloat的类似转换.一般的建议
(例如在Convert CGFloat to NSNumber in Swift)是
通过Double转换
CGFloat <--> Double <--> NSNumber
例:
let c1 = CGFloat(12.3) let num = NSNumber(double: Double(c1)) let c2 = CGFloat(num.doubleValue)
这很简单,也没有精确度.
现在大多数平台都是64位,然后是CGFloat / Double
转换很简单,可能由编译器优化.
然而,如果可以进行转换,它引起了我的好奇心
没有在32位平台上将CGFloat提升为Double.
可以使用构建配置语句(例如在Should conditional compilation be used to cope with difference in CGFloat on different architectures?中):
extension NSNumber { convenience init(cgFloatValue value : CGFloat) { #if arch(x86_64) || arch(arm64) self.init(double: value.native) #else self.init(float: value.native) #endif } }
但是如果将Swift移植到其他没有的架构上会怎么样呢
英特尔还是ARM?这看起来不是很好的证据.
也可以使用CGFLOAT_IS_DOUBLE常量(例如,在
NSNumber from CGFloat):
if CGFLOAT_IS_DOUBLE != 0 { // ... } else { // ... }
这里的缺点是编译器将始终发出一个
其中一个案件的“永远不会被执行”警告.
所以长话短说:
>我们如何在之间进行转换
CGFloat和NSNumber以安全的方式,没有编译器警告,
没有不必要的推广到Double?
请注意,这是一个“学术”问题.如上所述
在上面(以及在其他Q& A中),可以简单地通过Double进行转换
几乎.
我在这里发布了一个“自我回答”的精神
share your knowledge,Q&A-style.当然欢迎其他答案!
let c1 = CGFloat(12.3) let num = c1 as NSNumber let c2 = num as CGFloat
这保留了CGFloat的精度,并与Swift 2一起使用
和斯威夫特3.
(以前的答案 – 太复杂了):我找到了两种解决方案.第一个使用免费桥接
在NSNumber和CFNumber之间(如What is most common and correct practice to get a CGFloat from an NSNumber?所示)
for Objective-C).它使用CFNumber具有专用的事实
CGFloat值的转换模式:
extension NSNumber { // CGFloat -> NSNumber class func numberWithCGFloat(var value: CGFloat) -> NSNumber { return CFNumberCreate(nil,.CGFloatType,&value) } // NSNumber -> CGFloat var cgFloatValue : CGFloat { var value : CGFloat = 0 CFNumberGetValue(self,&value) return value } }
这很简单.唯一的缺点:我无法弄清楚
如何使构造函数成为init方法而不是类方法.
第二种可能的解决方案有点长:
extension NSNumber { // CGFloat -> NSNumber private convenience init(doubleOrFloat d : Double) { self.init(double : d) } private convenience init(doubleOrFloat f : Float) { self.init(float : f) } convenience init(cgFloat : CGFloat) { self.init(doubleOrFloat: cgFloat.native) } // NSNumber -> CGFloat private func doubleOrFloatValue() -> Double { return self.doubleValue } private func doubleOrFloatValue() -> Float { return self.floatValue } var cgFloatValue : CGFloat { return CGFloat(floatLiteral: doubleOrFloatValue()) } }
有两个私有的“helper”init方法具有相同的外部
参数名称为doubleOrFloat但参数类型不同.从实际出发
cgFloat.native的类型,编译器确定调用哪一个
在
convenience init(cgFloat : CGFloat) { self.init(doubleOrFloat: cgFloat.native) }
访问器方法中的相同想法.从self.native的类型
编译器确定两个doubleOrFloatValue()中的哪一个
要打电话的方法
var cgFloatValue : CGFloat { return CGFloat(floatLiteral: doubleOrFloatValue()) }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。