Objective-C Guide For Developers, Part 5

After seeing how classes and objects work in Objective-C, this part will be completely dedicated to types in Objective-C. This feature comes straight from C, but it’s still extensively used in Objective-C programming, including Apple libraries. Since you will encounter this quite often, it’s worth to spend some time having a look at this feature.

Table of contents

Defining custom types
Constants and enumerations
Bitwise operators and bitmasks
Structures

Defining custom types

We have already seen in the previous parts of this guide that there are two kinds of types a variable can have in Objective-C: basic types, as we have seen in the first part of this guide or object types, coming from classes either defined in Apple frameworks or defined by us. We have spent the last issues seeing how to create and extend the latter, but what about basic types? Can we define them too? If so, why would this be useful since we already have classes?

It turns out, of course, that we can indeed define new basic types, and actually we have already met some of these newly defined types, although I didn’t mention what they were. The C language basically offers only basic types for integers and floating point values. As we have seen, even the bool and char types are in the end just integers used in a different manner (and with a different byte size in memory, to be precise).

C, unlikely other languages like Java, allows also the definition of new basic types, the only condition being that these new types must be derived from the ones already provided by the language (or by composing them, as we will see later). In fact, the Objective-C basic types we encountered, like NSInteger or CGFloat, are just redefinitions of basic C types, namely long and double, respectively.

Why this redefinition? Could we not just use long and double instead? Of course we could, but there are some advantages in defining new types. The first one is clarity and legibility. CGFloat is not the only redefinition of the double type, there are also others, like NSTimeInterval. Despite being both the same type of value in memory, in our code we can clearly see that a variable of the first type represents graphical values, like coordinates on screen or sizes of graphical objects, while a variable of the second type represent an amount of time (in seconds, as defined by the documentation).

The other reason is one we already encountered, which is to differentiate the actual memory representation of a type based on the architecture in a way that is transparent to the developer. I said that a CGFloat is just a double, but actually that is not entirely correct: it’s a double on 64 bits architectures, while it’s a float on 32 bits ones. This redefinition allows the redefinition of the underlying representation of the types when needed, without requiring to change all the code that has been written up to that point (and this is exactly what happened to NSInteger and CGFloat in the transition from 32 to 64 bits architectures).

Now that we know the reasons to define new types, here is how to do it:

typedef existingType newType;

So, for example, if I want to define a type to represent people’s age as a positive integer, I can write:

typedef unsigned int Age;

or alternatively:

typedef NSUInteger Age;

I can then use this new type normally to define variables or properties in objects. Let’s rewrite our previous example of the Person class to include an age property:

typedef unsigned int Age;

@interface Person : NSObject

@property NSString *firstName;
@property NSString *lastName;
@property Age age;

@end

Constants and enumerations

Sometimes we need variables to be constant and to not change their value over time. This is easily done with the const keyword in front of a variable declaration:

const double Pi = 3.14159;

The compiler will make sure that the content of this variable is never changed and will emit an error if you try to assign a new value to it after this declaration.

(By the way, if you need pi it’s already defined as the M_PI constant, together with other common mathematical constants in the header file math.h, which is always available in C, so you don’t have to include it directly in your source files).

Sometimes though we need to define more constants to enumerate different options we might have and we don’t really care about the values these constants might have as long as they are different from each other (sometimes we might need these values to be ordered).

Let’s say we want to add a sex property to our Person class. The only values we want to allow are Male, Female and Undefined when sex is not specified (for simplicity of the example I will not include the various transgender identities, but when you deal with such kind of data in real like it’s helpful to not make the assumption that people only identify themselves with the two canonical sexes).

We could already use the const keyword for this and define each sex as an integer constant with values 0, 1 and 2. This would work but would be impractical for larger sets of constants, because when we needed to introduce a new value inside the order, we will have to change all the other values manuallyt. Luckily C has a special construct made for this, called enum, which stands for enumeration:

enum {
    FirstConstant,
    SecondConstant,
    ...
    LastConstant
};

In this way all the constants get consecutive values starting from 0. Notice that the last constant does not have a comma after it and there is a semicolon after the closing brace (these are two common mistakes that cause syntax errors). It’s also possible to start from a value different than 0:

enum {
    FirstConstant = number,
    SecondConstant,
    ...
    LastConstant
};

The consecutive constants will get incremental values starting from the selected number. It is even possible to assign an arbitrary value to each constant, if needed.

It does not stop here. It’s possible to use an enumeration to define a new type:

typedef enum {
    FirstConstant,
    SecondConstant,
    ...
    LastConstant
} TypeName;

Where the name of the type goes at the end, after the closing brace. Since iOS 6 and Mac OS 10.8, Apple introduces a new NS_ENUM macro, which is now the preferred way to define enumerations. I included the other ways in this guide for completeness, since you might still find them in some code bases or in Apple documentation, but you should use NS_ENUM for your enumerations:

typedef NS_ENUM(baseType, newTypeName) {
    FirstConstant,
    SecondConstant,
    ...
    LastConstant
};

This macro adds a baseType to ensure a fixed size for the newly defined type. It  also provides hints to the compiler for type-checking and switch statement completeness. It’s also a bit more readable since the new type name is at the top and not at the bottom.

We can now expand our Person class to include sex:

typedef unsigned int Age;

typedef NS_ENUM(NSUInteger, Sex) {
    Undefined,
    Male,
    Female
};

@interface Person : NSObject

@property NSString *firstName;
@property NSString *lastName;
@property Age age;
@property Sex sex;

@end

I put the Undefined constant at the beginning, so it will have a value of 0 which is the default value properties have when an object is created. We can then use the constants when creating our object:

Person *person = [Person new];
person.firstName = @“Matteo”;
person.lastName = @“Manferdini”;
person.age = 33;
person.sex = Male;

Pay attention though that the compiler does not enforce the values that we can assign to a variable with an enumeration type. So this will still compile and run perfectly fine:

person.sex = 7;

Apple makes extensive uses of enumerations in its classes. For example, to create a new button in iOS 7, you would use the +buttonWithType: factory method with a UIButtonTypeSystem type:

UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];

Bitwise operators and bitmasks

There is still a class of operators I didn’t mention over when I spoke about operators in Objective-C: bitwise operators. They are used for bitwise operations as the name implies, which are usually needed for some low level implementations (like network protocols), but can be used also for other purposes as we will now see. Like the other operators, these ones come directly from C. This is a table summing them up:

Operator   Description                        Syntax

&          bitwise and                        a & b
|          bitwise or                         a | b
^          bitwise xor                        a ^ b
<<         left shift                         a << b
>>         right shift                        a >> b
~          bitwise not, or one’s complement   ~a

Let’s see how they are usually used in Objective-C. With enumerations we have seen how we can create types that allow us to name different constants in a more readable way. The limitation with enumerations, though, is that a variable can only have one of the defined values at a time. What if we want to have a predefined set of options that are not mutually exclusive but can be set at the same time?

One way of doing this would be again to create a class with a boolean property for each option we want to enable simultaneously, but this would be an overkill and we would need to then assign or check every property singularly, making it very tedious to check all the options.

This special case can be handled easily with bitwise operators. We can make each constant in the enumeration have only one bit set to 1 and all others set to 0 (remember that we can assign an arbitrary value to an enumeration). Then, to specify multiple options at the same time we can use the bitwise or operator to group them in the same variable. Lets see how this works with an example.

Let’s say we want to have 4 non mutually exclusive options. We can declare an enumeration with bitmasks using the left shift operator. As we had the NS_ENUM macro for normal enumerations, we have the NS_OPTIONS macro for bitmask enumerations (but a simple typedef enum would still work, of course):

typedef NS_OPTIONS(NSUInteger, Options) {
    NoOptions = 0,
    Option1 =   1 << 0,
    Option2 =   1 << 1,
    Option3 =   1 << 2,
    Option4 =   1 << 3,
} Options;

The options will have the following bit representations in memory (I will omit leading zeros for clarity and only show the last 4 bits):

Option      Value

NoOptions   0000
Option1     0001
Option2     0010
Option3     0100
Option4     1000

When we want to group multiple options in the same variable, we can use the bitwise or operator:

Options enabledOptions = Option1 | Option3;

This groups the multiple options together in this way:

Option1          0001
Option3          0100
                 ----
enabledOptions   0101

As you can see, both the first and the third bit (from the right) are set in the enabledOptions variable, thus containing both values. To check wether any option is enabled we can use the bitwise and operator:

if (enabledOptions & Option1) {
    ...
}

If an option is enabled, operating a bitwise and on the value will produce a non zero value, that can be used as a true value in a condition. A bitwise and with a non enabled option produces a value of zero, which is equivalent to false.

You can use this in your code and Apple indeed does use it in different places. If we want to specify, for example, an autoresizing mask for a view with both flexible width and height, we can do it this way:

UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | 
                        UIViewAutoresizingFlexibleHeight;

Structures

Now, what if we want a variable to hold more than one value? One possibility is of course to create an object for that, as we have already seen, and in many languages this is the only option to achieve this purpose. But Objective-C inherits a feature from C that allows variables to contain more than one value, without being an object: structures.

You rarely need to create structures in your apps, but if you need something more lightweight than an object to contain simple values and with faster access a struct might be your tool. A structure is just a some space in memory that contains some values exactly as variables do, so it does not incur in the additional overhead of objects. A structure variable is declared with the keyword struct and can contain as many values as you want:

struct variableName {
    type memberName;
    ...
};

The syntax is similar to that of enumerations, but notice that here there is a semicolon after each member of the structure, because they act like variable declarations inside of the structure.

Let’s say, for example, that you want to store the value of a point on screen, which is identified by x and y coordinates. You can do so with a structure:

struct point {
    CGFloat x;
    CGFloat y;
};

You can then access the members with dot notation:

point.x = 100.0;
point.y = 200.0;

Or you can initialize the whole structure in one line using the following syntax with curly braces:

 point = {100.0, 200.0};

As happens for enumerations, you can turn structures into basic types to be able to reuse them:

typedef struct {
    type memberName;
    ...
} typeName;

This is exactly how the CGPoint type is declared, for example. CGPoint is used to store coordinates of graphical objects in iOS apps.

A disadvantage of structures over objects is that functionality needs to be defined externally. After all structures are only a basic type and cannot have methods attached. This requires you to write C functions to operate on them, which you usually don’t want to do. For example, CGPoint has a function to initialize a new structure:

CGPoint point = CGPointMake(100.0, 200.0);

or a function to compare two points:

if (CGPointEqualToPoint(point1, point2) {
    ...
}

Structures can also contain other structures, as in CGFrame, a type that indicated rectangles of graphical objects. A CGFrame has a origin, which is a CGPoint, and a size expressed in width and height, which is a CGSize. Under ARC, though, a structure cannot contain objects, so a structure can only be composed from other basic types.

These are structures you will encounter quite often, with other structures (like CGAffineTransform, for example, if you want to rotate, scale or translate graphical objects). There are a lot of functions in Apple frameworks to deal with these structures, but as you can see, this separates the functionality from the data, which defeats the Object Oriented Paradigm. For this reason it’s usually better to create a new class instead of a structure for your values, unless you have specific reasons like compatibility with C or C++ code, or to optimize execution speed.