我发现 Swift 数字特别笨拙,就像现实生活中经常发生的那样,我必须与 Cocoa Touch 就 CGRect 和 CGPoint 进行交流(例如,因为我们正在谈论某事frame
or bounds
).
CGFloat 与 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
is).
这个例子人为地简短,所以有一个人为地简单的解决方案,那就是强制转换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 时,这当然是错误的做法。我还没有弄清楚这两个项目之间的差异是什么导致错误出现在一个项目中而不是另一个项目中(也许其他人有)。
NOTE:我可能已经发现了这个问题:它似乎取决于“仅构建活动架构”构建设置,这反过来又表明这是一个 64 位问题。这是有道理的,因为 Float 在 64 位设备上与 CGFloat 不匹配。这意味着阻抗失配问题比我想象的还要严重。
结论
我正在寻找关于这个主题的实用智慧之言。我想有人可能已经设计了一些 CGRect 和 CGPoint 扩展,这将使生活变得更加轻松。 (或者可能有人编写了大量额外的算术运算符函数重载,这样将 CGFloat 与 Int 或 Double 结合起来“就可以工作”——如果可能的话。)