Faryar Fathi

Composer, Coder, Entrepreneur

Objective-C Literals

When I was introduced to Objective-C, its verbose syntax seemed annoying and even unnecessary. But I quickly learned to appreciate the clarity that it often provides and eventually that very same verbosity became one of the reasons that I enjoy writing code in Objective-C. However, there are a few frequently used classes in the Foundation framework that have literal equivalents, and I have opted to use them since they can make my code more concise, easier to read and easier to debug.

Let’s have a look at them, shall we?

Literal Strings

Chances are you are already using string literals without even knowing about it. Each time you write a line of code like:

1
 NSString *myString = @"Hello, World!";

The @"Hello, World!" part of your code is a string literal. Without using the literal syntax, you should have created your string object by allocating and initializing it or by using a factory method like this:

1
2
NSString *myString = [NSString stringWithCString:"Hello, World!"
                                        encoding:NSUTF8StringEncoding];

As you can see, the literal syntax is a lot cleaner and easier to read and write.

Literal Numbers

NSNumber is a handy class for wrapping integers, floats, doubles, chars and boolean values in an Objective-C object. The usual syntax for doing so is as follows:

1
2
3
4
5
NSNumber *myInt = [NSNumber numberWithInt:1];
NSNumber *myFloat = [NSNumber numberWithFloat:6.5f];
NSNumber *myDouble = [NSNumber numberWithDouble:3.14159];
NSNumber *myChar = [NSNumber numberWithChar:'a'];
NSNumber *myBool = [NSNumber numberWithBool:YES];

Again, you can make your code a lot cleaner and easier to read by using the literal equivalents:

1
2
3
4
5
NSNumber *myInt = @1;
NSNumber *myFloat = @6.5f;
NSNumber *myDouble = @3.14159;
NSNumber *myChar = @'a';
NSNumber *myBool = @YES;

Literal Arrays

Without using the literal syntax, arrays are usually created using a factory method such as arrayWithObjects: :

1
NSArray *languages = [NSArray arrayWithObjects:@"ObjC", @"Ruby", @"Python", nil];

As you can see arrayWithObjects: is a nil-terminated method, meaning that you must include nil as the last value to signal the end of your objects list.

The literal equivalent of above is:

1
NSArray *languages = @[@"ObjC", @"Ruby", @"Python"];

With literal syntax, we don’t have to terminate the list with nil. In fact, nil is an invalid value here and an exception is thrown if you try to include it.

Now consider a scenario where you have a list of objects to build an array with:

1
2
3
id objectOne = @"First Object";
id objectTwo = nil;
id objectThree = @"Third Object";

You could use arrayWithObjects: factory method to create your array:

1
NSArray *myArray = [NSArray arrayWithObjects:objectOne, objectTwo, objectThree];

Here, your array only contains one object (objectOne). Since objectTwo is nil, you have unintentionally truncated your array without even knowing about it.

Or, you could use the literal syntax:

1
NSArray *myArray = @[firstObject, secondObject, thirdObject];

In this case, an exception is thrown at runtime and your app crashes, which is not necessarily a bad thing! It is much easier to catch and fix a bug when an exception is thrown, rather than having to deal with a difficult to catch bug resulting from having an array with fewer than expected objects in it.

Literal syntax can also be used to query an array. Normally, to get an object at a specific index, you would use the objectAtIndex: method:

1
NSString *ruby = [languages objectAtIndex:1];

With literals, you can use what known as the subscript syntax, which makes is easier to see what’s going on and is also similar to how arrays are queried in other languages:

1
2

NSString *ruby = languages[1];

Literal Dictionaries

The standard factory method for creating a dictionary can be real confusing since the expected order of keys and objects is reversed:

1
2
3
4
5
6
 NSDictionary *pianoMusic = [NSDictionary dictionaryWithObjectsAndKeys:
                                     @"For Elise", @"title",
                                     @"Beethoven", @"composer",
                                     @"A minor", @"scale"
                                     [NSNumber numberWithInt:1867], @"publicationDate",
                                     nil];

Compare that with the literal syntax below to see how easier it is to see what’s going on:

1
2
3
4
 NSDictionary *pianoMusic = @{@"title" : @"For Elise",
                            @"composer" : @"Beethoven",
                                @"scale" : @"A minor",
                            @"publicationDate" : @1867};

As you can see, I have also used a literal NSNumber to make the code even cleaner! Here again, you need to be careful about nil, as you’ll get an exception at runtime if any of your objects is nil.

Similar to arrays, you can use the literal syntax to access dictionaries. The literal equivalent of:

1
NSString *composer = [pianoMusic objectForKey:@"composer"];

is:

1
NSString *composer = pianoMusic[@"composer"];

Mutable Arrays & Dictionaries

The literal syntax can also be used to set objects in mutable arrays and dictionaries:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Array
[mutableLanguages replaceObjectAtIndex:0 withObject:@"Objective-C"];
[mutableLanguages insertObject:@"Pearl" atIndex:3];
// Dictionary
[mutablePianoMusic setObject:@"L.V. Beethoven" forKey:@"composer"];

/**** using literal syntax  ****/

// Array
mutableLanguages[0] = @"Objective-C";
mutableLanguages[3] = @"Pearl";
// Dictionary
mutablePianoMusic[@"composer"] = @"L.V. Beethoven";

To Nil, or Not to Nil!

You might be wondering what if you want to represent nil in an array or a dictionary. Well… there is a way to represent the “no object” concept or nil in a collection class. And that’s by using NSNull:

1
NSArray *myArray = @[@"Hello, World!", [NSNull null]];

Final Words

I hope I have managed to show you how you can make your code more concise and easier to read by using the literal notation. Before I finish, it’s worth mentioning that the literal notation is just syntactic sugar. In other words, each time you use the literal syntax, behind the scenes the appropriate initializer or factory method is still called for you. And the good thing is, it’s called correctly, nil-terminated and all!