【发布时间】:2014-07-29 07:37:06
【问题描述】:
我发现 Swift 数字特别笨拙,因为在现实生活中经常发生这种情况,我必须与 Cocoa Touch 就 CGRect 和 CGPoint 进行交流(例如,因为我们谈论的是 frame 或 @987654323 @)。
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 就是这样)。
该示例人为地简短,因此有一个人为的简单解决方案,即从一开始就将scale 转换为浮点数。但是,当从各地提取的许多变量都涉及到提议的 CGRect 元素的计算中时,需要进行大量的转换。
详细初始化程序
另一个令人烦恼的事情是在创建新的 CGRect 时会发生什么。尽管有文档,但没有带有值但没有标签的初始化程序。这无法编译,因为我们有 Doubles:
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 试图通过将 Float 强制转换为 NSNumber 来“过桥”,当桥的另一边需要 CGFloat 时,这当然是错误的做法。我还没有弄清楚这两个项目之间的区别是什么导致错误出现在一个而不是另一个(也许其他人有)。
注意:我可能已经发现了这个问题:它似乎取决于 Build Active Architecture Only 构建设置,这反过来表明这是一个 64 位问题。这是有道理的,因为 Float 与 64 位设备上的 CGFloat 不匹配。这意味着阻抗失配问题比我想象的还要严重。
结论
我正在寻找关于这个话题的实用智慧之言。我想有人可能设计了一些 CGRect 和 CGPoint 扩展,这将使生活变得更轻松。 (或者可能有人写了一大堆额外的算术运算符函数重载,这样将 CGFloat 与 Int 或 Double 结合起来“就行了”——如果可能的话。)
【问题讨论】:
-
您是在 Open Radar 上提交错误报告,还是仅私下提交?
-
@JoshCaswell 私下,但如果您需要雷达编号和措辞,请离线联系我
-
在 Xcode 6 beta 5 中:CGFloat 可以从任何 Integer 类型(包括大小整数类型)构造,反之亦然。 (17670817)
-
好消息,感谢@BergQuester 的提醒