9

I'm simply trying to round the CGFloat return value of CGRectGetWidth.

override func layoutSubviews()  {
    let roundedWidth = roundf(CGRectGetWidth(self.bounds))
    ...
}

The compiler won't let me, giving the error:

'NSNumber' is not a subtype of 'CFloat'.

I guess there is some basic thing I am missing here. roundf is taking a CFloat as argument, so how can I convert my CGFloat to CFloat to make the conversion?

Update:

Now using round instead of roundf but I am still getting the same error. I've tried cleaning the project and restarting Xcode.

enter image description here

Anton
  • 5,932
  • 5
  • 36
  • 51

4 Answers4

5

CGRect members are CGFloats, which, despite their name, are actually CDoubles. Thus, you need to use round(), not roundf()

override func layoutSubviews()  {
    let roundedWidth = round(CGRectGetWidth(self.bounds))
    ...
}
johnyu
  • 2,152
  • 1
  • 15
  • 33
Ben Gottlieb
  • 85,404
  • 22
  • 176
  • 172
  • try let roundedWidth = roundf(self.bounds.width) – Calin Chitu Jun 03 '14 at 10:47
  • I'm not seeing any error when using `round()`, which accepts a `CDouble` (which actually is typealiased by `CGFloat`). This answer is correct. – akashivskyy Jun 03 '14 at 10:51
  • It is really not working for me. I can't understand why the compiler is still complaining. See the update in the question. – Anton Jun 03 '14 at 11:54
  • You're seeing differences because you're compiling for different architectures. @akashivskyy, CGFloat is only typealiased as CDouble when compiling for 64-bit architectures. If compiling for 32-bit architectures, it's typealiased as CFloat. (See [64-Bit Transition Guide](https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html), where it's pretty clearly stated that you can't rely on the underlying type of CGFloat.) – Matt Gibson Jun 12 '14 at 15:02
5

The problem is that CGFloat is platform dependent (just like it is in ObjC). In a 32 bit environment, CGFloat is type aliased to CFloat - in a 64 bit environment, to CDouble. In ObjC, without the more pedantic warnings in place, round was happy to consume your float, and roundf your doubles.

Swift doesn't allow implicit type conversions.

Try building for an iPhone 5 and a iPhone 5s simulator, I suspect you'll see some differences.

Jerry Jones
  • 5,393
  • 2
  • 22
  • 14
1

For some reason I needed to make an explicit typecast to CDouble to make it work.

let roundedWidth = round(CDouble(CGRectGetWidth(self.bounds)))

I find this pretty strange since a CGFloat is a CDouble by definition. Seems like the compilator got a bit confused here for some reason.

Anton
  • 5,932
  • 5
  • 36
  • 51
  • 1
    This does not work on iPhone 5, iPhone 4S, iPad 2 & iPad Retina. It only works on the 64-bit devices. – Oskar Persson Jun 12 '14 at 10:05
  • 2
    This [this question of mine](http://stackoverflow.com/questions/24184810/should-conditional-compilation-be-used-to-cope-with-difference-in-cgfloat-on-dif) for some more background on what's going on here. Basically it's because the underlying type of CGFloat changes depending on whether you're compiling for 32- or 64-bit architecture. – Matt Gibson Jun 12 '14 at 14:58
  • CFloat is of 32 bits while CDouble interprets according the platform. therefore is safest to use double – Baxter Lopez Jun 19 '14 at 14:28
  • That is **not** a type cast! You are creating a new CDouble with the initializer syntax. A type cast is with the keyword **as**. And CGFloat is only a CDouble on 64Bit systems as @Jerry Jones pointed out. – Binarian Jul 14 '14 at 12:20
1

CGFloat() works with all architectures for me.

MacMark
  • 6,239
  • 2
  • 36
  • 41