‘;CGFloat&x2019;不可转换为‘;UInt8';以及Swift和Xcode 6 beta 4的其他CGFloat问题

‘;CGFloat&x2019;不可转换为‘;UInt8';以及Swift和Xcode 6 beta 4的其他CGFloat问题,xcode,swift,type-conversion,operator-overloading,cs193p,Xcode,Swift,Type Conversion,Operator Overloading,Cs193p,如果这说明了问题所在,下面是原始的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行很好,为了清晰起见,我稍后将介绍它们 l

如果这说明了问题所在,下面是原始的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位构建时失败,反之亦然。(1724725)


我只是做错了什么?我甚至不知道如何更好地描述这个问题,以便向苹果提交beta 4的bug报告。几乎我拥有的每一个Swift项目都会受到这个问题的影响,所以我在寻找一些合理的解决方案。

@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相关,那么处理这个问题的正确方法是什么?有历史痕迹吗?应该删除吗?

也有同样的问题。。。试试包装

arc4random_uniform 


这对我有用。。。不知道为什么Swift/Xcode在转换无符号整数时出现问题

,因为Swift没有隐式类型转换,所以必须指定发生的所有类型转换。使这个例子特别乏味的是,当前Swift似乎缺少
CGFloat
和类型(如
UInt32
)之间的直接转换,您必须按照您发现的中间类型进行转换

最后,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)

TL;DR简单快捷方式导致HCF:停止并着火

请注意,有一些明显的工作法律解决方案,如实现与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 proceess+kernel_任务占用了10+千兆的RAM,消耗了我16千兆的剩余内存。花了很长时间才追溯到这一点——它并不迅速。

至于问题报告,我认为原因很简单,
UInt32
无法转换为
CGFloat
,反之亦然。发布为bug报告17758869事实上,
CGFloat
的转换问题似乎只是一种方式,您可以直接将
CGFloat
值转换为
UInt32
CGFloat(UInt(arc4random\u uniform(UInt32(bounds.size.width*5)))
我发现您的建议有错误,Rob,您使用的是beta 4吗?我必须按照Arkku的建议使用Uint或Int。beta 3的工作方式不同。谢谢!这帮我节省了很多时间。你真的应该像上面的答案那样用Uint把它包起来。将其包装为Int将起作用,但不建议这样做(尤其是在处理大数字时),因为这可能会导致精度损失。
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)
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) }
}