我发现Swift数字尤其笨拙,正如在现实生活中经常发生的那样,我必须就CGRect和CGPoint与Cocoa Touch进行沟通(例如,因为我们正在谈论某些事情frame
或者bounds
).
从UIViewController子类中考虑以下看似无辜的代码:
let scale = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.size.width * scale
Run Code Online (Sandbox Code Playgroud)
此代码无法编译,最后一行通常有神秘错误:
找不到接受提供的参数的'*'的重载
正如我现在所知道的那样,这个错误表明类型之间存在某种阻抗不匹配.r.size.width
作为CGFloat到达,它将与Swift Float自动交换,但不能与Swift Double变量(默认情况下是这样scale
)进行互操作.
这个例子是人为简短的,所以有一个人为简单的解决方案,即scale
从一开始就转换为Float.但是当从所有地方抽取的许多变量都参与了CGRect元素的计算时,需要进行大量的投射.
另一个恼人的是当创建新的CGRect时会发生什么.尽管有文档,但没有带有值但没有标签的初始值设定项.这无法编译,因为我们有双打:
let d = 2.0
var r3 = CGRect(d, d, d, d)
Run Code Online (Sandbox Code Playgroud)
但即使我们d
转向Float,我们也不会编译:
在调用中缺少参数标签'x:y:width:height:'
所以我们最终会重新开始CGRectMake
,这对Objective-C没有任何改进.有时CGRectMake和CGSizeMake没有任何改进.请考虑我的某个应用中的实际代码:
let kSEP : Float = 2.0
let intercellSpacing = CGSizeMake(kSEP, kSEP);
Run Code Online (Sandbox Code Playgroud)
在我的一个项目中,这是有效的.在另一个,它神秘失败 - 完全相同的代码! - 出现此错误:
'NSNumber'不是'CGFloat'的子类型
有时,Swift试图通过将Float转换为NSNumber来"过桥",当桥的另一侧需要CGFloat时,这当然是错误的.我还没有弄清楚导致错误出现在一个而不是另一个(可能是其他人有)的两个项目之间的区别.
注意:我可能已经发现了这个问题:它似乎依赖于Build Active Architecture Only构建设置,这反过来表明它是一个64位问题.这是有道理的,因为Float不会与64位设备上的CGFloat匹配.这意味着阻抗不匹配问题甚至比我想象的还要糟糕.
我正在寻找关于这个主题的实用智慧词.我想有人可能已经设计了一些CGRect和CGPoint扩展,这将使生活变得更加容易.(或者可能有人写了一大堆额外的算术运算符函数重载,这样将CGFloat与Int或Double结合起来"只是起作用" - 如果可能的话.)
Ber*_*ter 24
明确打字scale
来CGFloat
,因为你已经发现,确实是这样处理的打字问题迅速.供他人参考:
let scale: CGFloat = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.width * scale
Run Code Online (Sandbox Code Playgroud)
不确定如何回答您的第二个问题,您可能希望使用不同的标题单独发布.
更新:
Swift创建者和首席开发人员Chris Lattner在2014年7月4日的Apple开发者论坛上就此问题发表了这样的话:
这里发生的是CGFloat是Float或Double的类型,具体取决于你是构建32位还是64位.这正是Objective-C的工作方式,但在Swift中存在问题,因为Swift不允许隐式转换.
我们已经意识到这个问题并认为它是严肃的:我们现在正在评估几种不同的解决方案,并将在稍后的测试版中推出一个.正如您所注意到的,您可以通过强制转换为Double来应对此问题.这是不优雅但有效的:-)
在Xcode 6 Beta 5中更新:
CGFloat可以从任何Integer类型(包括大小的整数类型)构造,反之亦然.(17670817)
Sei*_*van 15
我写了一个处理运算符重载的库,允许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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用它来访问它 let someCGFloat = someDoubleOrInt.CGFloatValue
此外,对于您的CGRect初始化程序,您会得到缺少的参数标签错误,因为您已经关闭了标签,CGRect(x: d, y: d, width: d, height: d)
除非只有一个参数,否则您不需要保留标签.