Sunday, March 30, 2014

Passing CGFloat to methods resets the value of arguments to 0

Recently, I was faced a very weird issue with methods that have CGFloat as argument.

The Problem

We were using cocos2d for our iOS project.  The code was very simple, I was trying to invoke a method of class that takes two CGFloat arguments.

No matter what values I pass to doSomething it always receives 0 or some other garbage value.  Just to be extra sure, I even logged the values of the parameters passed before actually invoking the method.  The values got printed correctly, but the doSomething method always printed 0.

The Explanation

Well, I was stumped here.  This was like the simplest possible code.  Set the value of a variable, pass it to another method and BOOM the value gets reset!

Obviously, this was nothing to do with how I have written the code, others out there must be facing the same issue.  A bit of googling calmed my nerves.

CGFloat is just a typedef wrapper around either a float or a double. Whether it actually is a float or a double depends on the header where CGFloat is defined that your code compiled against.  The CGFloat definition looks something like this

Notice how CGFloat either becomes a float or a double, depending on whether the architecture is 64 bit or not.

All goes well, until you mix code compiled with this flag on, with other code compiled with this flag off (Such as including a binary library with other code). Effectively mixing 64 bit compiled code with 32 bit compiled code.

This can potentially lead to a case where we are passing doubles to methods that are expecting a float.  Since this is all happening at the byte level, no error is thrown and the bytes are just truncated, taking off all of the bits that actually described your value and leaving bits with nothing in them i.e. 0.

In my case, it was happening because I was trying to build a binary for both the Simulator and iPad Air Device.

The Solution

A clean and build should have solved the issue, but I decided to change the method arguments to float instead of CGFloat.  Once I did this change, everything worked as expected!
Thats all folks!  Until we meet again, enjoy your time.

Have some Fun!