In case this illuminates the problem, here's the original Objective-C code.
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);
I started out with this code. Lines 2 and 3 are fine, I'm presenting them for clarity later.
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)
In Xcode 6 beta 3, it was necessary to cast the arc4random_uniform UInt32 result to CGFloat in order for the minus and multiplication to work. This doesn't work anymore and the compiler shows an error:
‘CGFloat’ is not convertible to ‘UInt8’
The release notes state:
"CGFloat is now a distinct floating-point type that wraps either a Float on 32-bit architectures or a Double on 64-bit architectures. It provide all of the same comparison and arithmetic operations of Float and Double and may be created using numeric literals. Using CGFloat insulates your code from situations where your code would be !fine for 32-bit but fail when building for 64-bit or vice versa. (17224725)"
Am I just doing something wrong with types? I don't even know how to describe this problem better to submit a bug report to Apple for beta 4. Pretty much every single Swift project I have that does any kind of point or rect manipulation got hit by this issue, so I'm looking for some sanity.
Since Swift doesn't have implicit type conversions, you must specify all the type conversions that take place. What makes this case particularly tedious, is that currently Swift seems to lack direct conversions between CGFloat
and types such as UInt32
, and you must go through an intermediate type as you've discovered.
In the end, two double conversions are needed for the 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)