Adding Booleans to Objective-C Arrays and Dictionaries

A quick tip today on adding basic non-object types such as NSInteger and BOOL to Objective-C collection classes such as NSArray and NSDictionary.

Objective-C Primitive Data Types

The Objective-C language is a set of extensions to the standard C language. This means that many of the basic types are inherited from the underlying C language. This makes Objective-C different from some other object-oriented languages such as ruby where everything is an object.

The Cocoa Core Foundation framework defines NSInteger and NSUInteger types but if you look at the definitions in NSObjCRuntime.h you will see that they are just typedefs for the underlying int or unsigned int C types. One additional basic data type that Objective-C does add is BOOL but again if you take a look at its definition in objc.h you will see that BOOL is also not an object, it is actually just a char.

Adding Primitive Data Types to Collections

My guess is that most Cocoa and Cocoa Touch developers do not care how object-oriented Objective-C is. However the fact that not all types are objects can catch people out who are new to the language. Consider the following code to add some items to an array:

NSInteger score = 100;
BOOL flag = YES;

NSMutableArray *myArray = [NSArray array];
[myArray addObject:score];
[myArray addObject:flag];

This seems perfectly reasonable but both of the -addObject: method calls generate compiler warnings:

warning: passing argument 1 of 'addObject:' makes pointer from
integer without a cast

The definition of addObject: is as follows:

- (void)addObject:(id)anObject

As the definition suggests you can add any object you like to an array but it has to be an object. This discussion also applies to other Objective-C collection types such as NSMutableDictionary and NSMutableSet. Since neither NSInteger or BOOL are objects the compiler generates a warning to tip you off that something is probably wrong with your code.

The solution luckily is very simple. You need to first convert the integer and bool types to an object. The easiest way to do that is to convert them to an NSNumber which is a full Objective-C object. The NSNumber class has a number of class level factory methods which make creating an NSNumber object quick and easy:

[myArray addObject:[NSNumber numberWithInteger:score]];
[myArray addObject:[NSNumber numberWithBool:flag]];

These class methods create autoreleased NSNumber objects so we do not need to worry about calling release on these objects ourself. See this previous post for more discussion on Cocoa Factory Classes and Autorelease.

Retrieving Primitive Data Types from Collections

The process of extracting the integer and boolean types from the array is equally easy using the appropriate NSNumber instance methods to access the numeric values. In this case we need to use -integerValue and -boolValue on the NSNumber object returned from the array:

NSNumber *myScore = [myArray objectAtIndex:0];
NSInteger scoreValue = [myScore integerValue];
BOOL flagValue = [[myArray objectAtIndex:1] boolValue];