一尘不染

Swift数字和CGFloat(CGPoint,CGRect等)

swift

我发现Swift数值特别笨拙,因为在现实生活中经常发生这种情况,我必须就CGRect和CGPoint与Cocoa
Touch交流(例如,因为我们在谈论某事framebounds)。

CGFloat vs.双

考虑下面的来自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的时间到了。尽管有文档,但没有带有值但没有标签的初始化程序。由于我们有Doubles,因此无法编译:

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”的子类型

就像有时候,Sw​​ift试图通过将Float强制转换为NSNumber来“越过桥”,当桥另一侧的期望CGFloat时,这当然是错误的选择。我还没有弄清楚两个项目之间的区别是什么导致错误出现在一个项目中而不是另一个项目中(可能是其他人)。

注意:
我可能已经发现了这个问题:它似乎取决于“仅构建活动体系结构”构建设置,这又表明这是一个64位问题。这是有道理的,因为在64位设备上Float与CGFloat不匹配。这意味着阻抗失配问题甚至比我想象的还要严重。

结论

我正在寻找有关该主题的实用智慧之词。我认为有人可能已经设计了一些CGRect和CGPoint扩展,这将使生活更加轻松。(或者可能有人编写了许多附加的算术运算符函数重载,如可能,将CGFloat与Int或Double结合使用“就是可行的”)。


阅读 567

收藏
2020-07-07

共1个答案

一尘不染

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

https://github.com/seivan/ScalarArithmetic

从Beta 5开始,下面列出了您目前无法使用香草Swift进行的操作。
https://github.com/seivan/ScalarArithmetic#sample

我建议在有无ScalarArithmetic的情况下运行测试套件,只是为了看看发生了什么。

2020-07-07