繁体   English   中英

Swift数字和CGFloat(CGPoint,CGRect等)

[英]Swift numerics and CGFloat (CGPoint, CGRect, etc.)

我发现Swift数字尤其笨拙,正如在现实生活中经常发生的那样,我必须就CGRect和CGPoint与Cocoa Touch进行沟通(例如,因为我们谈论的是framebounds )。

CGFloat vs. Double

从UIViewController子类中考虑以下看似无辜的代码:

let scale = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.size.width * scale

此代码无法编译,最后一行通常有神秘错误:

找不到接受提供的参数的'*'的重载

正如我现在所知道的那样,这个错误表明类型之间存在某种阻抗不匹配。 r.size.width作为CGFloat到达,它将与Swift Float自动交换,但不能与Swift Double变量互操作(默认情况下,它是scale )。

这个例子是人为简短的,所以有一个人为简单的解决方案,即从一开始就将scale到Float。 但是当从所有地方抽取的许多变量都参与了CGRect元素的计算时,需要进行大量的投射。

详细初始化器

另一个恼人的是当创建新的CGRect时会发生什么。 尽管有文档,但没有带有值但没有标签的初始值设定项。 这无法编译,因为我们有双打:

let d = 2.0
var r3 = CGRect(d, d, d, d)

但即使我们将d转换为Float,我们也不会编译:

在调用中缺少参数标签'x:y:width:height:'

所以我们最终会回到CGRectMake ,这对Objective-C没有任何改进。 有时CGRectMake和CGSizeMake没有任何改进。 请考虑我的某个应用中的实际代码:

let kSEP : Float = 2.0
let intercellSpacing = CGSizeMake(kSEP, kSEP);

在我的一个项目中,这是有效的。 在另一个,它神秘失败 - 完全相同的代码! - 出现此错误:

'NSNumber'不是'CGFloat'的子类型

有时,Swift试图通过将Float转换为NSNumber来“过桥”,当桥的另一侧需要CGFloat时,这当然是错误的。 我还没有弄清楚导致错误出现在一个而不是另一个(可能是其他人有)的两个项目之间的区别。

注意:我可能已经发现了这个问题:它似乎依赖于Build Active Architecture Only构建设置,这反过来表明它是一个64位问题。 这是有道理的,因为Float不会与64位设备上的CGFloat匹配。 这意味着阻抗不匹配问题甚至比我想象的还要糟糕。

结论

我正在寻找关于这个主题的实用智慧词。 我想有人可能已经设计了一些CGRect和CGPoint扩展,这将使生活变得更加容易。 (或者可能有人写了一大堆额外的算术运算符函数重载,这样将CGFloat与Int或Double结合起来“只是工作” - 如果可能的话。)

正如您所发现的那样,明确scaleCGFloat键入scale确实是处理swift中的键入问题的方法。 供他人参考:

let scale: CGFloat = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.width * scale

不确定如何回答您的第二个问题,您可能希望使用不同的标题单独发布。

更新:

Swift创建者和首席开发人员Chris Lattner在2014年7月4日的Apple开发者论坛上就此问题发表了这样的话:

这里发生的是CGFloat是Float或Double的类型,具体取决于你是构建32位还是64位。 这正是Objective-C的工作方式,但在Swift中存在问题,因为Swift不允许隐式转换。

我们已经意识到这个问题并认为它是严肃的:我们现在正在评估几种不同的解决方案,并将在稍后的测试版中推出一个。 正如您所注意到的,您可以通过强制转换为Double来应对此问题。 这是不优雅但有效的:-)

在Xcode 6 Beta 5中更新:

CGFloat可以从任何Integer类型(包括大小的整数类型)构造,反之亦然。 (17670817)

我写了一个处理运算符重载的库,允许Int,CGFloat和Double之间的交互。

https://github.com/seivan/ScalarArithmetic

从Beta 5开始,这里列出了目前你无法用vanilla Swift做的事情。 https://github.com/seivan/ScalarArithmetic#sample

我建议运行带有和不带ScalarArithmetic的测试套件,看看是怎么回事。

我为Double和Int创建了一个扩展,它为它们添加了一个计算的CGFloatValue属性。

extension Double {
    var CGFloatValue: CGFloat {
        get {
            return CGFloat(self)
        }
    }
}
extension Int {
    var CGFloatValue: CGFloat {
        get {
            return CGFloat(self)
        }
    }
}

您可以使用let someCGFloat = someDoubleOrInt.CGFloatValue来访问它

另外,对于你的CGRect初始化程序,你得到了缺少的参数标签错误,因为你没有关闭标签,你需要CGRect(x: d, y: d, width: d, height: d)你不能留下标签除非只有一个论点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM