正如现实生活中经常发生的那样,当我不得不与Cocoa Touch就CGRect和CGPoint进行交流时(例如,因为我们谈论的是frame
或bounds
).
CGFloat vs Double
从UIVIEW控制器子类中考虑以下无害的代码:
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双变量交互(默认情况下,scale
就是这样).
这个例子是人为地简单,所以有一个人为地简单的解决方案,就是从一开始就把scale
抛到一个浮点数上.但是,当从各地抽取的许多变量都涉及到一个提议的CGRect元素的计算时,有很多铸造工作要做.
冗长初始值设定项
另一个恼人的问题是,到了创建新CGRect的时候会发生什么.尽管有文档,但没有带值但没有标签的初始值设定项.这无法编译,因为我们有两个:
let d = 2.0
var r3 = CGRect(d, d, d, d)
但即使我们将d
转换为一个浮点,我们也不会编译:
调用中缺少参数标签"x:y:width:height:"
所以我们最终还是回到了CGRectMake
,这对Objective-C来说并没有什么改善.有时CGRectMake和CGSizeMake也没有改善.从我的一个应用程序中考虑这个实际代码:
let kSEP : Float = 2.0
let intercellSpacing = CGSizeMake(kSEP, kSEP);
在我的一个项目中,这很有效.在另一个例子中,它神秘地失败了——完全相同的代码出现以下错误:
"NSNumber"不是"CGFloat"的子类型
有时,Swift 似乎试图通过向NSNumber抛出一个Float来"过桥",当然,当桥的另一边需要一个CGFloat时,这样做是错误的.我还没有弄清楚这两个项目之间的区别是什么,导致错误出现在其中一个项目中,而不是另一个项目中(可能是其他人).
NOTE:我可能已经解决了这个问题:它似乎取决于只构建活动体系 struct 的构建设置,这反过来表明这是一个64位的问题.这是有道理的,因为在64位设备上,Float与CGFloat不匹配.这意味着阻抗失配问题比我想象的还要严重.
结论
我在寻找关于这个话题的实用智慧之词.我在想,可能有人设计了一些CGRect和CGPoint扩展,这会让生活更轻松.(或者可能有人编写了大量额外的算术运算符函数重载,这样,将CGFloat与Int或Double结合起来"就行了"——如果可能的话.)