sobota, 18 kwietnia 2015

Solving the NSNumber mystery

Ignorance is bliss. I used NSNumber and didn't really care how it really works. One day when I had to find out what's inside NSNumber (bool, float or integer) that bubble burst.

It turned out that you can't really find out what NSNumber is holding with simply calling a method on the object, which is kind of illogical, given that you explicitly say what you put inside NSNumber and Obj-C is a dynamic language, right? I don't give up that easily, though. I digged more. What I discovered surprised me greatly.

NSNumber is a class cluster which is a special design pattern used to box private classes in one public class.

That means that we don't have to deal with a dozen of classes, as they are hidden behind the public class.

That also means that NSNumber points to a different Core Foundation class in reality, depending on what you decide it to be.

We can use that knowledge to find out what NSNumber instance is really holding:

So, NSNumber can point to either CFBoolean, or CFNumber. CFNumber can hold any type of number primitive. We cast to (void*) or (CFNumberRef) to keep the compiler happy.

Unfortunately, even though Foundation lets us forget about Core Foundation, sometimes we have to go back and use the lower layer.

Every Objective-C programmer should have some knowledge about underlying Core Foundation framework, as it gives you more control, it can allow you to create some neat hacks (like the one above), and some libraries are Core Foundation exclusive (Keychain access for example).