【问题标题】:‘CGFloat’ is not convertible to ‘UInt8' and other CGFloat issues with Swift and Xcode 6 beta 4'CGFloat' 不能转换为 'UInt8' 和 Swift 和 Xcode 6 beta 4 的其他 CGFloat 问题
【发布时间】:2014-07-21 19:33:42
【问题描述】:

如果这能说明问题,这里是原始的 Objective-C 代码。

int x = (arc4random()%(int)(self.gameView.bounds.size.width*5)) - (int)self.gameView.bounds.size.width*2;
int y = self.gameView.bounds.size.height;
drop.center = CGPointMake(x, -y);

我从这段代码开始。第 2 行和第 3 行很好,为了清楚起见,我稍后再展示它们。

let x = CGFloat(arc4random_uniform(UInt32(self.gameView.bounds.size.width * 5))) - self.gameView.bounds.size.width * 2
let y = self.gameView.bounds.size.height
dropView.center = CGPointMake(x, -y)

在 Xcode 6 beta 3 中,必须将 arc4random_uniform UInt32 结果转换为 CGFloat 才能使减法和乘法起作用。这不再起作用,编译器显示错误:

‘CGFloat’不能转换为‘UInt8’

发行说明状态:

“CGFloat 现在是一种独特的浮点类型,它在 32 位架构上封装了 Float,在 64 位架构上封装了 Double。它提供了 Float 和 Double 的所有相同比较和算术运算,并且可以创建使用数字文字。使用 CGFloat 将您的代码与您的代码可能出现的情况隔离开来 ! 适用于 32 位,但在构建 64 位时失败,反之亦然。 (17224725)"

我只是在类型上做错了吗?我什至不知道如何更好地描述这个问题,以便向 Apple 提交 beta 4 的错误报告。我拥有的几乎每个 Swift 项目都受到了这个问题的影响,所以我寻找一些理智。

【问题讨论】:

  • 关于问题报告,我觉得很简单,UInt32不能转换成CGFloat,反之亦然。
  • 发布为错误报告 17758869

标签: xcode swift type-conversion operator-overloading cs193p


【解决方案1】:

由于 Swift 没有隐式类型转换,您必须指定所有发生的类型转换。让这个案例特别乏味的是,目前 Swift 似乎缺乏CGFloatUInt32 等类型之间的直接转换,并且您必须通过您发现的中间类型。

最后arc4random_uniform需要两次双重转换:

let bounds = CGRectMake(0.0, 0.0, 500.0, 500.0)
var x = CGFloat(UInt(arc4random_uniform(UInt32(UInt(bounds.size.width) * 5))))
x -= bounds.size.width * 2
let center = CGPointMake(x, -bounds.size.height)

【讨论】:

  • 其实CGFloat的转换问题似乎只有一种方式,可以直接将CGFloat的值强制转换为UInt32CGFloat(UInt(arc4random_uniform(UInt32(bounds.size.width * 5))))
  • 我发现您的建议有错误 Rob,您使用的是 beta 4 吗?我不得不按照 Arkku 的建议使用 Uint 或 Int。 beta 3 的工作方式不同。
【解决方案2】:

遇到同样的问题...尝试换行

arc4random_uniform 

Int()

喜欢

Int(arc4random_uniform)

这对我有用...不知道为什么 Swift/Xcode 在转换无符号 INT 时遇到问题

【讨论】:

  • 谢谢你!为我节省了很多时间。
  • 您应该像上面的答案那样将它真正包装在 Uint 中。将其包装为 Int 可以,但不建议使用(尤其是在处理大量数字时),因为它可能会导致精度损失。
【解决方案3】:

TL;DR 简单快捷方式导致 HCF: Halt 和 Catch Fire 错误

请注意,有一些明显的工作合法解决方法,例如实现与 CGFloat 的转换:

完全合法,但不要这样做:

extension Float {
    func __conversion() -> CGFloat { return CGFloat(self) }
}

extension CGFloat {
    func __conversion() -> Float { return Float(self) }
    func __conversion() -> Double { return Double(self) }
}

extension Double {
    func __conversion() -> CGFloat { return CGFloat(self) }
}

我打字的时候没有注意到,但是后来我的机器一直过热和挂起,SourceKit 达到 300-500%,并且 swift 进程 + kernel_task 占用了 10+ gigs 的 RAM,消耗了我 16 gigs 中剩下的所有内容.花了很长时间才追查到这一点 - 它并不迅速。

【讨论】:

    【解决方案4】:

    @Arkku 提供了正确的解决方案,因此 x 的单行是...

    let x = CGFloat(UInt(arc4random_uniform(UInt32(UInt(self.gameView.bounds.size.width) * 5)))) - self.gameView.bounds.size.width * 2
    

    从 Xcode 6 beta 5 开始,您仍然可以根据需要使用中间转换,并且您的代码将继续工作。但是,它不再需要,因此现在可以按预期进行以下操作。

    let x = CGFloat(arc4random_uniform(UInt32(self.gameView.bounds.size.width * 5))) - self.gameView.bounds.size.width * 2
    

    由于原始问题仅与 Xcode 6 beta 4 相关,那么处理该问题的正确方法是什么?有历史印记吗?是否应该删除?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 2020-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-10
      • 2016-10-22
      相关资源
      最近更新 更多