由于 Swift 缺少 CGFloat 的隐式转换而造成的混乱
Posted
技术标签:
【中文标题】由于 Swift 缺少 CGFloat 的隐式转换而造成的混乱【英文标题】:Confusion due to Swift lacking implicit conversion of CGFloat 【发布时间】:2014-07-29 20:48:11 【问题描述】:尝试在返回 `CGFloat 的函数中进行算术运算,但出现错误:
找不到接受提供的参数的“/”的重载
func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
return (M_PI * (x) / 180.0) // error is here.
有没有其他人看到过这种类型的问题?
【问题讨论】:
这不是重复的。虽然抛出的错误是相同的,但这里的根本原因比对类型安全和类型推断的误解要微妙得多。 @Mani,我建议您尝试为您的问题想一个不同的标题。事实上,它会导致与所谓的重复内容混淆,并且可能会让您的问题被仅根据标题投票的人关闭。 @Cezar 我已经编辑了我的标题,如果你觉得这个标题让人困惑,请随时编辑我的标题。 【参考方案1】:这是double
到float
转换的问题。
在 64 位机器上,CGFloat
定义为 double
,您将毫无问题地编译它,因为 M_PI
和 x
都是双精度的。
在 32 位机器上,CGFloat
是 float
,但 M_PI
仍然是双精度。不幸的是,Swift 中没有隐式转换,因此您必须显式转换:
return (CGFloat(M_PI) * (x) / 180.0)
180.0
字面量的类型是推断出来的。
在 Swift 3 中
M_PI
已弃用,请改用CGFloat.pi
:
return (x * .pi / 180.0)
【讨论】:
我的脑海中仍然在流淌着 C 和 Objective-C,这就是问题所在。我接到你了。工作正常。谢谢@Sulthan..【参考方案2】:最好抽象出复杂性。首先创建一个扩展
extension Double
/** Converts the specified value in degrees into radians. */
func degrees() -> CGFloat
return CGFloat(self) * CGFloat(M_PI / 180.0)
然后在您的代码中使用它,例如以下示例
let angle = 30.0.degrees()
let transform = CGAffineTransformRotate(self.sliderControl.transform, angle);
起初我不愿意扩展 Double,因为我不喜欢创建定制的语言使用(来自 C++ 中的编码恐惧)。然而,实践经验表明这是一种语言自然的抽象方式。
【讨论】:
【参考方案3】:在这种特殊情况下,我有一个可爱的技巧要推荐
let π = CGFloat(M_PI)
Unicode 无处不在,π 很容易用 Opt+P
【讨论】:
+1 用于使用 unicode 符号名称,这不会像大多数人那样吓到我 :D (我想知道您是否可以将其添加为扩展名,因为CGFloat.π
会很明显它是一种什么样的价值……)【参考方案4】:
这应该可以修复错误:
func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
return (CGFloat(M_PI) * (x) / 180.0)
发生错误的原因是x
被明确声明为CGFloat
,而M_PI
的类型为CDouble
,如声明中所示:
var M_PI: CDouble get /* pi */
因此,您需要将M_PI
转换为类型CGFloat
,使其与x
的类型匹配(正如我在上面的代码中所做的那样)。这样,不同类型的操作就不会发生冲突了。
请注意,与其他答案(以及@Cezar 评论)中所述相反,您不需要将 180.0
显式转换为 CGFloat
类型,因为它是literal,并且没有显式类型,因此会自动转换为CGFloat
,无需手动转换。
【讨论】:
至少应该有一个编译器标志来关闭这种纳粹类型检查。它真的会扼杀生产力 有,叫-x objective-c
@PartialyFinite 具有不同类型的生产力 ki]]。以上是关于由于 Swift 缺少 CGFloat 的隐式转换而造成的混乱的主要内容,如果未能解决你的问题,请参考以下文章
TransferValue - 在 TreeView ItemsSource 中生成的隐式转换器 <null>