3. Interface and API Design

Once you have built an application, you are likely going to want to reuse parts of the code for future projects. You may even want to release some of the code for others to use. Even if you don’t think that you’re going to do either of these things, you probably will at some point. When you do, it’ll help to write your interfaces in such a way that they fit in. This means using paradigms commonly used with Objective-C and understanding various pitfalls.

Over recent years, especially with the open-source community and components made popular with the advent of iOS, it is common to use other people’s code in your own applications. Similarly, others may end up using your code, so writing in a clear way will enable them to quickly and easily integrate your code. And who knows, you may end up writing the next library that is used in thousands of applications!

Item 15: Use Prefix Names to Avoid Namespace Clashes

Unlike other languages, Objective-C has no built-in namespace feature. For this reason, it is easy for names to clash unless measures are taken to avoid the potential. The impact a naming clash has on an application is that it may not link, owing to duplicate symbol errors like this:

Click here to view code image

duplicate symbol _OBJC_METACLASS_$_EOCTheClass in:
    build/something.o
    build/something_else.o
duplicate symbol _OBJC_CLASS_$_EOCTheClass in:
    build/something.o
    build/something_else.o

This error results because the symbol for the class and metaclass (see Item 14) symbols for a class called EOCTheClass have been defined twice, from two implementations of a class called EOCTheClass in two separate parts of the application’s code, perhaps from two separate libraries that you are pulling in.

Even worse than not linking would be if one of the libraries that contained one of the duplicates were loaded at runtime. In this case, the dynamic loader would encounter the duplicate symbol error and most likely bring down the entire application.

The only way to avoid this problem is to use a crude form of namespacing: prefixing all your names with a certain prefix. The prefix you choose should be relevant to your company, application, or both. For example, if your company were named Effective Widgets, you might decide to use the prefix EWS for code common to all your applications and EWB for code just for the application called Effective Browser. It’s still not impossible to have clashes when you prefix your names, but it is much less likely.

If you are creating applications using Cocoa, it is important to note that Apple has stated that it reserves the right to use all two-letter prefixes, so you should definitely choose a three-letter prefix in this case. For example, an issue could have arisen by not following these guidelines and deciding to use the TW prefix. When the iOS 5.0 SDK came out, it brought along the Twitter framework, which too uses the TW prefix, which has a class called TWRequest for making HTTP requests to the Twitter API. You could very easily also have had a class called TWRequest if you had an API of your own, for a company called Tiny Widgets, for example.

The prefixing should not stop with class names but should apply to all names that you have within your application. Item 25 explains the importance of prefixing category names and the methods within them if the category is on an existing class. Another important and often overlooked potential for conflict is pure C functions or global variables you use within the implementation files of your classes. It’s often easy to forget that these will appear as top-level symbols within your compiled object files. For example, the AudioToolbox framework in the iOS SDK has a function for playing a sound file. You can give it a callback that gets called when it finishes. You might decide to write a class to wrap this up into an Objective-C class that calls a delegate when the sound file finishes, like so:

Click here to view code image

// EOCSoundPlayer.h
#import <Foundation/Foundation.h>

@class EOCSoundPlayer;
@protocol EOCSoundPlayerDelegate <NSObject>
- (void)soundPlayerDidFinish:(EOCSoundPlayer*)player;
@end

@interface EOCSoundPlayer : NSObject
@property (nonatomic, weak) id <EOCSoundPlayerDelegate> delegate;
- (id)initWithURL:(NSURL*)url;
- (void)playSound;
@end

// EOCSoundPlayer.m
#import "EOCSoundPlayer.h"
#import <AudioToolbox/AudioToolbox.h>

void completion(SystemSoundID ssID, void *clientData) {
    EOCSoundPlayer *player =
        (__bridge EOCSoundPlayer*)clientData;
    if ([player.delegate
            respondsToSelector:@selector(soundPlayerDidFinish:)])
    {
        [player.delegate soundPlayerDidFinish:player];
    }
}

@implementation EOCSoundPlayer {
    SystemSoundID _systemSoundID;
}

- (id)initWithURL:(NSURL*)url {
    if ((self = [super init])) {
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)url,
                                         &_systemSoundID);
    }
    return self;
}

- (void)dealloc {
    AudioServicesDisposeSystemSoundID(_systemSoundID);
}

- (void)playSound {
    AudioServicesAddSystemSoundCompletion(
        _systemSoundID,
        NULL,
        NULL,
        completion,
        (__bridge void*)self);
    AudioServicesPlaySystemSound(_systemSoundID);
}

@end

This looks completely innocuous, but looking at the symbol table for the object file created from this class, we find the following:

Click here to view code image

00000230 t -[EOCSoundPlayer .cxx_destruct]
0000014c t -[EOCSoundPlayer dealloc]
000001e0 t -[EOCSoundPlayer delegate]
0000009c t -[EOCSoundPlayer initWithURL:]
00000198 t -[EOCSoundPlayer playSound]
00000208 t -[EOCSoundPlayer setDelegate:]
00000b88 S _OBJC_CLASS_$_EOCSoundPlayer
00000bb8 S _OBJC_IVAR_$_EOCSoundPlayer._delegate
00000bb4 S _OBJC_IVAR_$_EOCSoundPlayer._systemSoundID
00000b9c S _OBJC_METACLASS_$_EOCSoundPlayer
00000000 T _completion
00000bf8 s l_OBJC_$_INSTANCE_METHODS_EOCSoundPlayer
00000c48 s l_OBJC_$_INSTANCE_VARIABLES_EOCSoundPlayer
00000c78 s l_OBJC_$_PROP_LIST_EOCSoundPlayer
00000c88 s l_OBJC_CLASS_RO_$_EOCSoundPlayer
00000bd0 s l_OBJC_METACLASS_RO_$_EOCSoundPlayer

Note the symbol lurking in the middle, called _completion. This is the completion function created to handle when the sound has finished playing. Even though it’s defined in your implementation file and not declared in the header file, it still appears as a top-level symbol like this. Thus, if another function called completion is created somewhere, you’ll end up with a duplicate-symbol error when linking, such as the following:

duplicate symbol _completion in:
    build/EOCSoundPlayer.o
    build/EOCAnotherClass.o

Worse still would be if you were shipping your code as a library for others to use in their own applications. If you exposed a symbol called _completion like this, anyone using your library would not be able to create a function called completion, which is a nasty thing for you to do.

So you should always prefix C functions like this as well. In the preceding example, you could call the completion handler EOCSoundPlayerCompletion, for example. This also has the side effect that if the symbol ever appears in a backtrace, it’s easy to determine what code the problem has come from.

You should be particularly careful of the duplicate-symbol problems when you use third-party libraries and ship your code as a library that others plug into their own applications. If the third-party libraries that you use are also going to be used by the application, it’s easy for duplicate-symbol errors to arise. In that case, it’s common to edit all the code of the libraries you use to prefix them with your own prefix. For example, if your library is called EOCLibrary and you pull in a library called XYZLibrary, you would go through and prefix all names in XYZLibrary with EOC. The application is then free to use XYZLibrary itself, without the chance of a naming collision, as shown in Figure 3.1.

Figure 3.1 Avoiding naming clashes where a third-party library is included twice: once by the application itself and once by another library

Going through and changing all the names might seem like a rather tedious thing to do, but it’s prudent if you want to avoid naming collisions. You may ask why it’s necessary to do this at all and why the application can’t simply not include XYZLibrary itself and use your implementation of it. It’s possible to do that as well, but consider the scenario in which the application pulls in a third library, ABCLibrary, that has also decided to use XYZLibrary. In that case, if you and the author of ABCLibrary hadn’t prefixed, the application would still get duplicate-symbol errors. Or if you use version X of XYZLibrary but the application requires features from version Y, it would want its own copy anyway. If you spend time using popular third-party libraries with iOS development, you will frequently see this kind of prefixing.

Things to Remember

Choose a class prefix that befits your company, application, or both. Then stick with that prefix throughout.

If you use a third-party library as a dependency of your own library, consider prefixing its names with your own prefix.

Item 16: Have a Designated Initializer

All objects need to be initialized. When initializing an object, you sometimes don’t need to give it any information, but often you do. This is usually the case if the object cannot perform its action without knowing this information. An example from UIKit, the iOS UI framework, is UITableViewCell, which requires being told its style and an identifier to group cells of different types, enabling efficient reuse of cell objects that are expensive to create. The term given to the initializer that gives the object the required amount of information to perform its task is the “designated initializer.”

If there is more than one way to create an instance of a class, the class may have more than one initializer. This is perfectly fine, but there should still be just the one designated initializer through which all other initializers call. An example of this is NSDate, which has the following initializers:

Click here to view code image

- (id)init
- (id)initWithString:(NSString*)string
- (id)initWithTimeIntervalSinceNow:(NSTimeInterval)seconds
- (id)initWithTimeInterval:(NSTimeInterval)seconds
                 sinceDate:(NSDate*)refDate
- (id)initWithTimeIntervalSinceReferenceDate:
                               (NSTimeInterval)seconds
- (id)initWithTimeIntervalSince1970:(NSTimeInterval)seconds

The designated initializer in this case is initWithTimeIntervalSinceReferenceDate:, as explained in the documentation for the class. This means that all the other initializers call through to this initializer. Thus, the designated initializer is the only place where internal data is stored. If the underlying data store is changed for any reason, only one place needs to be changed.

For example, consider a class that represents a rectangle. The interface would look like this:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCRectangle : NSObject
@property (nonatomic, assign, readonly) float width;
@property (nonatomic, assign, readonly) float height;
@end

Taking heed of Item 18, the properties are read-only. But that means that there’s no way in which a Rectangle object can ever have its properties set externally. So you might introduce an initializer:

Click here to view code image

- (id)initWithWidth:(float)width
          andHeight:(float)height
{
    if ((self = [super init])) {
        _width = width;
        _height = height;
    }
    return self;
}

But what if someone decides to create a rectangle by calling [[EOCRectangle alloc] init]? Doing so is legitimate, since EOCRectangle’s superclass, NSObject, implements a method called init, which simply sets all instance variables to 0 (or equivalent of 0 for that data type). If that method is invoked, the width and height will stay set at 0 from when the EOCRectangle instance was allocated (in the call to alloc) in which all instance variables are set to 0. Although this might be what you want, you will more likely want to either set the default values yourself or throw an exception to indicate that an instance must be intialized using your designated initializer only. In the case of EOCRectangle, this would mean overriding the init method, like so:

Click here to view code image

// Using default values
- (id)init {
    return [self initWithWidth:5.0f andHeight:10.0f];
}

// Throwing an exception
- (id)init {
    @throw [NSException
            exceptionWithName:NSInternalInconsistencyException
             reason:@"Must use initWithWidth:andHeight: instead."
           userInfo:nil];

}

Note how the version that sets default values calls straight through to the designated initializer. This version could have been implemented by directly setting the _width and _height instance variables. However, if the storage backing the class had changed—for example, by using a structure to hold the width and height together—the logic of how to set the data would have to be changed in both initializers. This wouldn’t be too bad in this simple example, but imagine a more complicated class with many more initializers and more complicated data. It would be very easy to forget to change one of the initializers and end up with inconsistencies.

Now imagine that you want to subclass EOCRectangle and create a class called EOCSquare. It’s clear that this hierarchy makes sense, but what should the initializer be? Clearly, the width and height should be forced to be equal, since that’s what a square is! So you might decide to create an initializer like so:

Click here to view code image

#import "EOCRectangle.h"

@interface EOCSquare : EOCRectangle
- (id)initWithDimension:(float)dimension;
@end

@implementation EOCSquare

- (id)initWithDimension:(float)dimension {
    return [super initWithWidth:dimension andHeight:dimension];
}

@end

This would become EOCSquare’s designated initializer. Note how it calls its superclass’s designated initializer. If you look back to the implementation of EOCRectangle, you’ll see that it too calls its superclass’s designated initializer. This chain of designated initializers is important to maintain. However, it’s still possible for callers to initialize an EOCSquare object by using either the initWithWidth:andHeight: or the init method. You don’t really want to allow this, since someone could end up creating a square whose width and height don’t match. This illustrates an important point when subclassing. You should always override the designated initializer of your superclass if you have a designated initializer with a different name. In the case of EOCSquare, you could override EOCRectangle’s designated initializer like so:

Click here to view code image

- (id)initWithWidth:(float)width andHeight:(float)height {
    float dimension = MAX(width, height);
    return [self initWithDimension:dimension];
}

Note how the designated initializer of EOCSquare has been called. In implementing this, the method called init will also just magically work. Recall how in EOCRectangle, it was implemented to call through to EOCRectangle’s designated initializer with default values. It will still do this, but since the initWithWidth:andHeight: method has been overridden, EOCSquare’s implementation will be called, which in turn calls through to its designated initializer. So everything will still work, and there’s no way of creating an EOCSquare with unequal sides.

Sometimes, you won’t want to override the superclass’s designated initializer, as it doesn’t make sense. For example, you might decide that it’s not very nice that an EOCSquare object created with the initWithWidth:andHeight: method has its dimension set to the maximum of the two values passed in. You might decide that it’s a user error instead. In this case, the common pattern is to override the designated initializer and throw an exception:

Click here to view code image

- (id)initWithWidth:(float)width andHeight:(float)height {
    @throw [NSException
        exceptionWithName:NSInternalInconsistencyException
                   reason:@"Must use initWithDimension: instead."
                 userInfo:nil];
}

This might seem harsh, but it’s sometimes required, since it would leave an object being created with inconsistent internal data. In the case of EOCRectangle and EOCSquare, it would mean that calling init would also cause the exception to be thrown, because init calls through to initWithWidth:andHeight:. In that case, you might decide to override init and call initWithDimension: with a sensible default:

Click here to view code image

- (id)init {
    return [self initWithDimension:5.0f];
}

However, throwing an exception in Objective-C should mean that the error is fatal (see Item 21), so throwing an exception from an initializer should be a last resort if the instance cannot be initialized otherwise.

In some situations, you may need to have more than one designated initializer. These situations arise when an instance of the object can be created in two distinct ways and must be handled separately. An example of this is the NSCoding protocol, a serialization mechanism that allows objects to dictate how they should be encoded and decoded. This mechanism is used extensively throughout AppKit and UIKit, the two UI frameworks from Mac OS X and iOS, respectively, to provide the ability for objects to be serialized using an XML format called a NIB. These NIBs are usually used to store a view controller’s layout of its views. When loaded from a NIB, the view controller goes through the unarchiving process.

The NSCoding protocol defines that the following initializer method should be implemented:

- (id)initWithCoder:(NSCoder*)decoder;

This method can’t usually call through to your main designated initializer, because it has to do different work to unarchive the object through the decoder. Also, if the superclass implements NSCoding as well, its initWithCoder: method needs to be called. You would end up with two designated initializers in the strict sense of the term, because more than one initializer calls through to a superclass initializer.

Applying this to EOCRectangle would give the following:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCRectangle : NSObject <NSCoding>
@property (nonatomic, assign, readonly) float width;
@property (nonatomic, assign, readonly) float height;
- (id)initWithWidth:(float)width
          andHeight:(float)height;
@end

@implementation EOCRectangle

// Designated initializer
- (id)initWithWidth:(float)width
          andHeight:(float)height
{
    if ((self = [super init])) {
        _width = width;
        _height = height;
    }
    return self;
}

// Superclass's designated initializer
- (id)init {
    return [self initWithWidth:5.0f andHeight:10.0f];
}

// Initializer from NSCoding
- (id)initWithCoder:(NSCoder*)decoder {
    // Call through to super's designated initializer
    if ((self = [super init])) {
        _width = [decoder decodeFloatForKey:@"width"];
        _height = [decoder decodeFloatForKey:@"height"];
    }
    return self;
}

@end

Note how the NSCoding initializer calls through to the superclass designated initializer rather than one of its own. However, if the superclass also implements NSCoding, it would call through to that initializer instead. For example, consider EOCSquare:

Click here to view code image

#import "EOCRectangle.h"

@interface EOCSquare : EOCRectangle
- (id)initWithDimension:(float)dimension;
@end

@implementation EOCSquare

// Designated initializer
- (id)initWithDimension:(float)dimension {
    return [super initWithWidth:dimension andHeight:dimension];
}

// Superclass designated initializer
- (id)initWithWidth:(float)width andHeight:(float)height {
    float dimension = MAX(width, height);
    return [self initWithDimension:dimension];
}

// NSCoding designated initializer
- (id)initWithCoder:(NSCoder*)decoder {
    if ((self = [super initWithCoder:decoder])) {
        // EOCSquare's specific initializer
    }
    return self;
}

@end

In the same way that any initializer is chained through to the superclass implementation, initWithCoder: calls it first before continuing to do anything specific that it needs to do. In this way, EOCSquare is also fully NSCoding compliant. If you called through to your own initializer here or to a different superclass initializer, EOCRectangle’s initWithCoder: would never get called for EOCSquare instances, and so the _width and _height instance variables would not be decoded.

Things to Remember

Implement a designated initializer in your classes, and document which one it is. All other initializers should call through to this one.

If the designated initializer is different from the superclass, ensure that its designated initializer is overridden.

Throw an exception in initializers overridden from superclasses that should not be used in the subclass.

Item 17: Implement the description Method

While debugging, you will often find it useful to print out an object to inspect it. One way is to write logging code to print out all the properties of the object. But the most usual way is to do something like this:

NSLog(@"object = %@", object);

When the string to log is built up, object will be sent the description message and put in place of the %@ in the format string. So, for instance, if the object were an array, the output might look like this:

Click here to view code image

NSArray *object = @[@"A string", @(123)];
NSLog(@"object = %@", object);

Which outputs this:

object = (
  "A string",
  123
)

However, if you try this on a class of your own, you’ll often see something that looks more like this:

object = <EOCPerson: 0x7fd9a1600600>

That is not as helpful as the array! Unless you override description in your own class, the default implementation from NSObject will be invoked. The method is defined on the NSObject protocol, but the NSObject class implements it. Many methods are part of the NSObject protocol, and it’s done this way because NSObject is not the only root class. NSProxy is an example of another root class, which conforms to the NSObject protocol. Because methods like description are defined within the protocol, subclasses of these other root classes also must implement them. That implementation doesn’t do much, as you can see. What it does do is show the class name alongside the memory address of the object. This would be useful to you only if you wanted to see whether two objects were exactly the same object. However, you can’t tell any more about the objects than that. It’s more likely that you are going to want to know some more information about the object.

To make the output more useful, all you need to do is override description to return the string you want to represent your object. For example, consider a class to describe a person:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCPerson : NSObject

@property (nonatomic, copy, readonly) NSString *firstName;
@property (nonatomic, copy, readonly) NSString *lastName;

- (id)initWithFirstName:(NSString*)firstName
               lastName:(NSString*)lastName;

@end

@implementation EOCPerson

- (id)initWithFirstName:(NSString*)firstName
               lastName:(NSString*)lastName
{
    if ((self = [super init])) {
        _firstName = [firstName copy];
        _lastName = [lastName copy];
    }
    return self;
}

@end

A typical description method implementation for this would be as follows:

Click here to view code image

- (NSString*)description {
    return [NSString stringWithFormat:@"<%@: %p, \"%@ %@\">",
            [self class], self, _firstName, _lastName];
}

If this were to be used, the output for an object of type EOCPerson would now look like the following:

Click here to view code image

EOCPerson *person = [[EOCPerson alloc]
                      initWithFirstName:@"Bob"
                               lastName:@"Smith"];
NSLog(@"person = %@", person);
// Output:
// person = <EOCPerson: 0x7fb249c030f0, "Bob Smith">

This is clear and contains much more useful information. I suggest displaying the class name and pointer address just like the default implementation, simply because it’s useful to see sometimes. Although as you saw earlier, NSArray doesn’t do this, and there certainly is no rule about it. What you choose to put in the description is whatever makes sense for the object in question.

A simple way to write a description method containing a lot of different bits of information is to piggyback on NSDictionary’s description method. It returns something that looks like this:

{
    key: value;
    foo: bar;
}

This compact description can be used by forming a dictionary within your own description method and returning a string containing this dictionary’s description method. For example, the following class describes a location with a title and coordinates (latitude and longitude):

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCLocation : NSObject
@property (nonatomic, copy, readonly) NSString *title;
@property (nonatomic, assign, readonly) float latitude;
@property (nonatomic, assign, readonly) float longitude;
- (id)initWithTitle:(NSString*)title
           latitude:(float)latitude
          longitude:(float)longitude;
@end

@implementation EOCLocation

- (id)initWithTitle:(NSString*)title
           latitude:(float)latitude
          longitude:(float)longitude
{
       if ((self = [super init])) {
              _title = [title copy];
              _latitude = latitude;
              _longitude = longitude;
       }
       return self;
}

@end

It would be nice if the description method for this showed the title as well as the latitude and longitude. If an NSDictionary were used, the description method would look like this:

Click here to view code image

- (NSString*)description {
    return [NSString stringWithFormat:@"<%@: %p, %@>",
            [self class],
            self,
            @{@"title":_title,
              @"latitude":@(_latitude),
              @"longitude":@(_longitude)}
           ];
}

The output would look like this:

Click here to view code image

location = <EOCLocation: 0x7f98f2e01d20, {
    latitude = "51.506";
    longitude = 0;
    title = London;
}>

This is much more useful than just the pointer and class name, and all the properties of the object are nicely presented. You could also have used a string format that was formed of each of the instance variables, but the NSDictionary approach is easier to maintain when more properties are added to the class and want to form part of the description method.

Another method to be aware of, also part of the NSObject protocol, is debugDescription, whose purpose is very similar to description. The difference is that debugDescription is the method called when you invoke the print-object command within the debugger. The default implementation within the NSObject class simply calls directly through to description. For example, taking the EOCPerson class, running an application in the debugger (LLDB in this case), and pausing at a breakpoint just after creating an instance looks like this:

Click here to view code image

EOCPerson *person = [[EOCPerson alloc]
                         initWithFirstName:@"Bob"
                                  lastName:@"Smith"];
NSLog(@"person = %@", person);
// Breakpoint here

When the breakpoint has been hit, the debug console will be ready to receive input. The command po in LLDB will perform the print-object function, yielding the following:

Click here to view code image

EOCTest[640:c07] person = <EOCPerson: 0x712a4d0, "Bob Smith">
(lldb) po person
(EOCPerson *) $1 = 0x0712a4d0 <EOCPerson: 0x712a4d0, "Bob Smith">

Note that the (EOCPerson *) $1 = 0x712a4d0 is added by the debugger. The portion after that is what is returned from the debug-description method.

You may decide to make the normal description of an EOCPerson to be just the person’s name and then implement the debug-description method to provide the more thorough description. In that case, the two methods would look like this:

Click here to view code image

- (NSString*)description {
    return [NSString stringWithFormat:@"%@ %@",
            _firstName, _lastName];
}

- (NSString*)debugDescription {
    return [NSString stringWithFormat:@"<%@: %p, \"%@ %@\">",
            [self class], self, _firstName, _lastName];
}

This time, running the same code as previously and using the print-object command will yield the following:

Click here to view code image

EOCTest[640:c07] person = Bob Smith
(lldb) po person
(EOCPerson *) $1 = 0x07117fb0 <EOCPerson: 0x7117fb0, "Bob Smith">

This output can be particularly useful when you don’t want all that extra information about the class name and pointer address to be visible in the normal description but still want the ability to access it easily during debugging. An example of a class that does this from the Foundation framework is NSArray. For example:

Click here to view code image

NSArray *array = @[@"Effective Objective-C 2.0", @(123), @(YES)];
NSLog(@"array = %@", array);
// Breakpoint here

In that case, running, stopping at the breakpoint, and printing out the array object looks like this:

Click here to view code image

EOCTest[713:c07] array = (
    "Effective Objective-C 2.0",
    123,
    1
)
(lldb) po array
(NSArray *) $1 = 0x071275b0 <__NSArrayI 0x71275b0>(
Effective Objective-C 2.0,
123,
1
)

Things to Remember

Implement the description method to provide a meaningful string description of instances.

If the object description could do with more detail for use during debugging, implement debugDescription.

Item 18: Prefer Immutable Objects

When designing a class, you will, ideally, be making good use of properties (see Item 6) to encapsulate data. When using properties, you can limit the property to read-only. Keeping properties at the default, read-write, makes all your classes mutable. Often, however, the data being modeled does not need to be mutable. For example, if the data represents an object that has come from a read-only web service, such as a list of points of interest to display on a map, it makes no sense for such objects to be mutable. If such an object is mutated, the data will never be pushed back to the server. As illustrated in Item 8, if mutable objects are stored in collections, a set’s internal data structures can easily become inconsistent if objects held in the set are mutated. Therefore, I recommend making objects only as mutable as they need to be.

In practice, this means making properties read-only externally and exposing only the data that needs to be exposed. For example, consider a class to handle points of interest on a map where the data comes in from a web service. You might start out with a class that looks like this:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCPointOfInterest : NSObject

@property (nonatomic, copy) NSString *identifier;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, assign) float latitude;
@property (nonatomic, assign) float longitude;

- (id)initWithIdentifier:(NSString*)identifier
                   title:(NSString*)title
                latitude:(float)latitude
               longitude:(float)longitude;

@end

All the values come from the web service, and the identifier is to be used to refer to a point of interest in communications with the service. Once a point of interest has been created from a communication with the web service, it doesn’t make any sense to be able to change any of the values. In other languages, you would probably have created the instance variables as private, using whatever language construct were available, and have only a get accessor for the variable. However, in using properties in Objective-C, it is incredibly easy to be lazy and not consider private variables at all.

In order to make the EOCPointOfInterest class immutable, you would add the readonly attribute to all the properties:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCPointOfInterest : NSObject

@property (nonatomic, copy, readonly) NSString *identifier;
@property (nonatomic, copy, readonly) NSString *title;
@property (nonatomic, assign, readonly) float latitude;
@property (nonatomic, assign, readonly) float longitude;

- (id)initWithIdentifier:(NSString*)identifier
                   title:(NSString*)title
                latitude:(float)latitude
               longitude:(float)longitude;

@end

This now ensures that if anyone tries to change one of the properties’ values, a compiler error will be generated. The values can still be read but cannot be changed, so the data of an EOCPointOfInterest cannot become inconsistent. Thus, anyone making use of this object can be assured that the data is not going to be changed from underneath it. The object’s own data structures won’t become inconsistent. In the case of a map view displaying EOCPointOfInterest objects, the latitude and longitude of displayed points of interest are not going to change from underneath.

You might wonder why you need to bother setting the memory-management semantic attributes on the property, since there is not going to be a setter. Well, you could simply leave it as the default, like this:

Click here to view code image

@property (nonatomic, readonly) NSString *identifier;
@property (nonatomic, readonly) NSString *title;
@property (nonatomic, readonly) float latitude;
@property (nonatomic, readonly) float longitude;

However, it’s useful to document what memory-management semantics you are using in the implementation, and it makes it easier to make the property read-write later if you need to.

You may want to be able to alter the data encapsulated by an object within the object itself but not from the outside. In this case, the usual procedure is to redeclare the readonly property internally as readwrite. Of course, this opens up the possibility of race conditions when the property is nonatomic. It’s possible for an observer to read the property at the same time it is being written internally. This possibility should be overcome by ensuring that all access, including internally, is synchronized, if necessary, by using, for example, a dispatch queue (see Item 41).

Redeclaring the property as readwrite internally can be done by using the class-continuation category (see Item 27) whereby you can declare the same property as found in the public interface so long as it has the same attributes and expands on the readonly versus readwrite status. In the case of EOCPointOfInterest, for example, the class-continuation category might look like this:

Click here to view code image

#import "EOCPointOfInterest.h"

@interface EOCPointOfInterest ()
@property (nonatomic, copy, readwrite) NSString *identifier;
@property (nonatomic, copy, readwrite) NSString *title;
@property (nonatomic, assign, readwrite) float latitude;
@property (nonatomic, assign, readwrite) float longitude;
@end

@implementation EOCPointOfInterest

/* ... */

@end

Now, the properties can be set internally only within the EOCPointOfInterest implementation. More accurately, it is still possible for something external to the object to set those properties through the use of Key-Value Coding (KVC), whereby they could use setValue:forKey: like so:

[pointOfInterest setValue:@"abc" forKey:@"identifier"];

This would set the value of the identifier property because KVC would look through your class for a setIdentifier: method that does exist even though it’s not exposed through the public interface. However, this would be seen as an intrusion of your class’s API, and if anything goes wrong from doing a hack like this, it’s left up to that developer to pick up the pieces.

A brutal developer could even get around not having a setter by using introspection on the class to determine the offset of the property’s instance variable within the instance’s memory layout. The developer could then manually set the instance variable this way. But that would be even more of an invasion of your public API. So just because it is technically possible to work around the lack of a public setter, you shouldn’t ignore the advice to make your objects immutable.

Another thing to keep in mind when defining the public API to your classes is whether collection-class properties should be mutable or immutable. If, for instance, you have a person represented by a class that can store references to the person’s friends, you might want a property to get a list of all the friends of that person. If friends can be added and removed from the person, you would have a mutable set backing the property. In such a case, the usual way of exposing the friends set would be to have a readonly property that returns an immutable set that is a copy of the internal mutable set. For example, the following defines such a class:

Click here to view code image

// EOCPerson.h
#import <Foundation/Foundation.h>

@interface EOCPerson : NSObject

@property (nonatomic, copy, readonly) NSString *firstName;
@property (nonatomic, copy, readonly) NSString *lastName;
@property (nonatomic, strong, readonly) NSSet *friends;

- (id)initWithFirstName:(NSString*)firstName
            andLastName:(NSString*)lastName;
- (void)addFriend:(EOCPerson*)person;
- (void)removeFriend:(EOCPerson*)person;

@end
// EOCPerson.m
#import "EOCPerson.h"

@interface EOCPerson ()
@property (nonatomic, copy, readwrite) NSString *firstName;
@property (nonatomic, copy, readwrite) NSString *lastName;
@end

@implementation EOCPerson {
    NSMutableSet *_internalFriends;
}

- (NSSet*)friends {
    return [_internalFriends copy];
}

- (void)addFriend:(EOCPerson*)person {
    [_internalFriends addObject:person];
}

- (void)removeFriend:(EOCPerson*)person {
    [_internalFriends removeObject:person];
}

- (id)initWithFirstName:(NSString*)firstName
            andLastName:(NSString*)lastName {
    if ((self = [super init])) {
        _firstName = firstName;
        _lastName = lastName;
        _internalFriends = [NSMutableSet new];
    }
    return self;
}

@end

You could have declared the friends property as an NSMutableSet and let users of the class add people directly to that set themselves rather than going through the addFriend: and removeFriend: methods. But this would decouple the data too much and is an easy way for bugs to arise. If you had chosen to do this, an EOCPerson’s internal set of friends could be changed from underneath it, potentially causing issues if, for example, the person object wanted to do something else when a friend is added or removed. If the set is altered from underneath it, without its knowing, the object would become inconsistent.

On that note, it is also important not to introspect any object returned to you to find out whether it’s mutable. For example, you might be interfacing with a library that contains the EOCPerson class. The developer of that library might not have bothered to hand back a copy of the internal mutable set but instead opted to return the internal mutable set itself. This is legitimate and might be desirable if the set is likely to be extremely large, in which case taking a copy could be costly. It is legal to return an NSMutableSet, since it is a subclass of NSSet, in which case you might be tempted to do something like this:

Click here to view code image

EOCPerson *person = /* ... */;
NSSet *friends = person.friends;
if ([friends isKindOfClass:[NSMutableSet class]]) {
    NSMutableSet *mutableFriends = (NSMutableSet*)friends;
    /* mutate the set */
}

However, you should avoid that at all costs. It is not the contract that you have with the EOCPerson class, so you should not use introspection techniques like this. The point still stands that the object might not be able to cope with its data changing from beneath it. Therefore, you should not assume that you can.

Things to Remember

When possible, create objects that are immutable.

Extend read-only properties in a class-continuation category to read-write if the property will be set internally.

Provide methods to mutate collections held by objects rather than exposing a mutable collection as a property.

Item 19: Use Clear and Consistent Naming

The naming of classes, methods, variables, and so on is an important factor in Objective-C. Newcomers often consider the language verbose because it uses a syntax structure that ensures that the code can be read like a sentence. Names often include prepositions (“in,” “for,” “with,” etc.), whereas other languages consider their use somewhat superfluous. For example, consider the following section of code:

Click here to view code image

NSString *text = @"The quick brown fox jumped over the lazy dog";
NSString *newText =
    [text stringByReplacingOccurrencesOfString:@"fox"
                                    withString:@"cat"];

This code could be considered a long-winded way to write what seems such a simple expression. After all, the method to perform the replacing is 48 characters long. But this definitely reads just like a sentence:

“Take text and give me a new string by replacing the occurrences of the string “fox” with the string “cat”.”

That sentence perfectly describes what is going on. In languages that are less verbose, a similar procedure might look like this:

Click here to view code image

string text = "The quick brown fox jumped over the lazy dog";
string newText = text.replace("fox", "cat");

But in which order are the parameters to text.replace()? Will “fox” be replaced by “cat” or vice versa? Also, does the replace function replace all occurrences or just the first one? It’s not very clear. The Objective-C way of naming, however, is completely clear at the expense of more verbosity.

You will also note the use of camel casing—with a lowercase first letter—in method and variable names. Also, class names are always camel cased with an uppercase first letter and are also usually prefixed with two or three letters (see Item 15). This is the style most commonly used throughout Objective-C code. You could use your own style if you so wished, but using camel case will ensure that your names fit and feel right in the Objective-C world.

Method Naming

If you have come from a language such as C++ or Java, you’ll be used to functions being fairly concise in name and having to look at the function prototype in order to determine what the parameters do. This makes it very difficult to read code, though, since you often have to refer back to the prototype to remember what the function does. For example, consider a class that represents a rectangle. In C++, you might define it like so:

Click here to view code image

class Rectangle {
public:
    Rectangle(float width, float height);
    float getWidth();
    float getHeight();
private:
    float width;
    float height;
};

If you’re not familiar with C++, that doesn’t matter. All you need to be aware of is that this defines a class that has two instance variables: width and height. It also has a single way to create an instance of the class, called a constructor, that takes the dimensions. It also has accessors for the dimensions. When using the class, you would create an instance like this:

Rectangle *aRectangle = new Rectangle(5.0f, 10.0f);

When you come to look back at this code, it is not obvious what the 5.0f and the 10.0f represent. You could probably assume that it’s the dimensions of the rectangle, but is it the width or the height first? You would need to look back at the definition of the function to find out.

Objective-C overcomes this problem by being much more verbose in the naming of methods. A first effort at an equivalent class in Objective-C from someone familiar with C++ might be as follows:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCRectangle : NSObject

@property (nonatomic, assign, readonly) float width;
@property (nonatomic, assign, readonly) float height;

- (id)initWithSize:(float)width :(float)height;

@end

The person writing the class like this has obviously seen that the equivalent of constructors is the init- family of methods and chosen to use the method name initWithSize::. This might already look strange to you, and perhaps you think that having no characters before the second semicolon is syntactically incorrect. In fact, the syntax is perfectly sound, although it looks wrong because it suffers from the same problem as the C++ function name in that if you used the class, you’d be in the same position of not knowing which variable is which:

Click here to view code image

EOCRectangle *aRectangle =
    [[EOCRectangle alloc] initWithSize:5.0f :10.0f];

A much better method name is the following:

- (id)initWithWidth:(float)width andHeight:(float)height;

This is verbose, but there is absolutely no ambiguity over what each variable is when it is used like so:

Click here to view code image

EOCRectangle *aRectangle =
    [[EOCRectangle alloc] initWithWidth:5.0f andHeight:10.0f];

Newcomers to Objective-C often have difficulty getting used to the verbose naming of methods, although using verbose naming enhances the readability of code. Don’t be afraid to use long method names. Ensuring that method names are as long as they need to be means that they do precisely what they say. But you shouldn’t have incredibly long names either. Your method names should be concise and precise.

Take, for example, the EOCRectangle class. Well-named methods would include the following:

Click here to view code image

- (EOCRectangle*)unionRectangle:(EOCRectangle*)rectangle
- (float)area

However, badly named versions of those methods would include:

Click here to view code image

- (EOCRectangle*)union:(EOCRectangle*)rectangle // Unclear
- (float)calculateTheArea // Too verbose

Clearly named methods will read left to right in a manner that flows just as if you were reading a passage of text. Following the many rules that define how methods should be named is not mandatory, but doing so will certainly make your code maintainable and more readable by others.

The NSString class is a great place to look for a class that follows good naming-convention guidelines. Here are a few of the methods and why they are named the way they are:

+ string

Factory method to create a new, empty string. The type of the return value is indicated clearly by the method name.

+ stringWithString:

Factory method to create a new string that is identical to another string. Just as with the factory method to create an empty string, the return type is indicated by the first word in the method.

+ localizedStringWithFormat:

Factory method to create a new, localized string with the specified format. The return type is indicated as the second word of the method name here because a modifier is applied to the logical return type. Even though it’s still a “string” being returned, it is a more specific kind of string because it has been localized.

- lowercaseString

Convert a string by converting all uppercase characters into lowercase. It creates a new string rather than transforming the receiver, so it follows the rule of the return type being part of the method name. A modifier is applied, though, so that precedes the type.

- intValue

Parse a string as an integer. Because the return type is int, that is the first word. Usually, you would not abbreviate types like this; for example, string is never shortened to str, but int is the type name, so it is fine here. The method name is suffixed with Value to make it other than a single word. Single words are usually used for properties. Since int is not a property of the string, Value is added to qualify what is meant.

- length

Obtain the length (number of characters) of the string. This is a single phrase because it is, in effect, a property of the string. It will unlikely be backed by an instance variable, but it is nevertheless still a property of the string. An example of a bad name for this method is stringLength. The string is superfluous, since the receiver of the method is known to be a string.

- lengthOfBytesUsingEncoding:

Obtain the length of the byte array if the string is encoded using the given encoding (ASCII, UTF8, UTF16, etc.). This is similar to length, so the same reasons apply from that description. Additionally, a parameter is required by the method. The method name places the parameter immediately after the noun describing its type.

- getCharacters:range:

Obtain the individual characters within a given range of the string. This is an example of where get is used as a prefix, something that is not done for accessors, unlike in some other languages. The reason it’s used here is that the characters are returned via the array that is passed in as the first argument. The full method signature is as follows:

- (void)getCharacters:(unichar*)buffer range:(NSRange)aRange

The first parameter, buffer, should be a pointer to an array large enough to hold the characters in the requested range. The method returns through a parameter (often referred to as an out-parameter) like this, rather than through the return value, since it makes more sense from a memory-management perspective. The caller of the method handles all memory management rather than having creation be performed by the method and requiring the caller to free it. The second parameter is prefixed by a noun describing its type, just as for any parameter. Sometimes, these parameter names are prefixed with a preposition; for example, this method could be named getCharacters:inRange:. This is usually done if extra significance is required for that parameter over any other parameters.

- hasPrefix:

Determine whether the string is prefixed by another string. The return type is a Boolean, so it’s common here to use has to make any use of it read like a sentence. For example:

[@"Effective Objective-C" hasPrefix:@"Effective"] == YES

If the name were simply prefix:, it would not read as well as it does. Similarly, it could be named isPrefixedWith:, but that would be longer and sound more clumsy.

- isEqualToString:

Determine whether two strings are equal. The return type is a Boolean, so just as with hasPrefix:, the method name starts with is to ensure that the method reads like a sentence. Another place that is is used as a prefix is with Boolean properties. If the property name were enabled, for example, the accessors would usually be called setEnabled: and isEnabled.

In summary, following a few rules will help you write well-named methods.

If the method returns a newly created value, the first word in the method name should be its type, unless a qualifier needs to go in front, such as with the localizedString methods. This excludes property accessors, as they do not logically create a new object, even though they may return a copy of an internal object. These accessors should be named after the property they represent.

A parameter should be immediately preceded by a noun describing its type.

Methods that cause an action to happen on an object should contain a verb followed by a noun (or multiple nouns) if the method requires parameters to perform the action.

Avoid abbreviations, such as str, and instead use full names, such as string.

Prefix Boolean properties with is. Methods that return a Boolean but are not direct properties should be prefixed by either has or is, depending on what makes sense for that method.

Reserve the prefix get for use with methods that return values via an out-parameter, such as those that fill a C-style array.

Class and Protocol Naming

Classes and protocols should be given a prefix to avoid namespace clashes (see Item 15) and should be structured so that they read left to right, just like methods do. For example, in the class NSArray and its mutable counterpart subclass, NSMutableArray, mutable comes before array because it describes a specialization of the type.

To illustrate the naming conventions, consider the following, taken from the iOS UI library, UIKit:

UIView (class)

This is a class from which all “views” inherit. They are the building blocks of the user interface and perform the drawing of buttons, text fields, and tables. The name of the class is self-explanatory and uses the UI prefix used throughout the UIKit framework.

UIViewController (class)

A view (UIView) handles drawing views but is not responsible for controlling what is displayed within the view. That is the job of this class: a “view controller.” It is named in such a way that it maintains the left-to-right readability.

UITableView (class)

This is a specific type of view to display a list of items in a table. So it is named as the superclass prefixed with a qualifier to distinguish the kind of view it is. This prefixing of the superclass is a common theme throughout the naming conventions. It could be named simply UITable, but that would not be fully clear that it was a view. You would need to look up in the interface declaration to be sure what it was. If you were to create a specific table view designed to display images, you could create a subclass called EOCImageTableView, for example. You always prepend your own prefix, though, rather than use the prefix of the superclass (UIKit’s UI prefix in this case). The reason is that you have no right to add something to another framework’s namespace, and the other framework may decide to make an identically named class in the future.

UITableViewController (class)

Just as UITableView is a specific kind of view, this is a special kind of view controller designed specifically to control a table view. It is therefore named in a similar manner.

UITableViewDelegate (protocol)

This protocol defines an interface through which a table view can communicate with another object and is named after the class for which it defines the delegate interface, which ensures left-to-right readability. (See Item 23 for more information on the Delegate pattern.)

Above all, you should be consistent with your naming. Also, if you are subclassing a class within another framework, make sure to stick to its conventions. For example, if you create a custom view by subclassing UIView, make sure that the final word of the class name is View. Similarly, if you create your own delegate protocol, you should name it as the class it is a delegate for, followed by the word Delegate. Adhering to this naming structure will ensure that your code makes sense when you come back to it later or another person uses it.

Things to Remember

Follow the naming that has become standard in Objective-C to create interfaces that fit in and feel right.

Ensure that method names are concise but precise, and make their use read left to right just like a sentence.

Avoid using abbreviations of types in method names.

Most important, make sure that method names are consistent with your own code or that with which it is being integrated.

Item 20: Prefix Private Method Names

It’s extremely common for a class to do much more than it appears on the outside. When writing a class implementation, it is common to write methods that are used only internally. For such methods, I suggest that you prefix their names with something. This helps with debugging by clearly separating the public methods from the private ones.

Another reason for using a marker for private methods arises when considering changing a method name or signature. If the method is public, a change such as this should be thought about more carefully, since it might not be ideal to change the public API to a class. Thus, consumers of the class would have to update their code as well. However, if the method is an internal one, only the class’s own code need change, with no effect on the public-facing API. Using a marker to indicate private methods means that this distinction is easy to see when making such a change.

The prefix to use depends on your personal preference. Good choices of characters to include in a prefix are underscores and the letter p. My preference is for the prefix to be p_, since the p indicates “private,” and the underscore gives a visual gap before the start of the method name. The method name then continues in the usual camel case, with a lowercase first letter. For example, a class called EOCObject with private methods might look like this:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCObject : NSObject
- (void)publicMethod;
@end

@implementation EOCObject

- (void)publicMethod {
    /* ... */
}

- (void)p_privateMethod {
    /* ... */
}

@end

Unlike the public method, the private method does not appear in the interface definition. Sometimes, you will want to declare the private method in the class-continuation category (see Item 27); however, recent compiler changes mean that a method does not need to be declared before it is used. So usually, private methods will be declared only in their implementation.

If you’ve come from a language such as C++ or Java, you’re probably wondering why you have to do this rather than simply declaring the method private. In Objective-C, there is no way to mark a method as private. All objects are able to respond to all messages (see Item 12), and it’s possible to inspect an object at runtime to determine which messages it will respond to (see Item 14). Method lookup for a given message is performed at runtime (see Item 11), and there is no mechanism for limiting the scope of who, what, or when a certain method can be invoked. It is left to naming conventions to dictate semantics such as private methods. Newcomers may not feel comfortable with this, but embracing the dynamism of Objective-C unleashes its power. Taming the dynamism is crucial, though, and using naming conventions is one way to achieve this.

Apple tends to use a single underscore to prefix its private methods. So you might think that it would be a good idea to follow Apple’s cue and also use an underscore. However, this would be a potentially disastrous decision; if you did this in a subclass of an Apple-provided class, you could inadvertently override one of its methods. For this reason, Apple has documented that you should avoid using an underscore as the prefix. It is possibly a downside to the language that there is no way to indicate that a method should exist only in a certain scope, but it is part of the powerful, dynamic method dispatch system (see Item 11), which has many upsides also.

This scenario is potentially not as uncommon as you may think. For example, if you are creating a view controller in an iOS application, you subclass UIViewController. The view controller may hold a lot of state. You want a method that is used to clear all that state, which will be run whenever the view controller comes on screen. So you may end up implementing that method like this:

Click here to view code image

#import <UIKit/UIKit.h>

@interface EOCViewController : UIViewController
@end

@implementation EOCViewController
- (void)_resetViewController {
    // Reset state and views
}
@end

However, it turns out that UIViewController also implements a method called _resetViewController! The version from EOCViewController will be run whenever you call it and for all times that the original version should be run. You wouldn’t know that unless you went digging deep into the library, as the method name is not exposed. After all, it’s a private method as denoted by the underscore. In this situation, you might end up with strange things happening to the view controller because the original implementation is never called, or you might get confused as to why your version is being called much more often than it should be.

In sum, when you subclass a class in a framework that is neither Apple’s nor your own, you cannot know what private prefix, if any, the framework is using unless it is documented. In this case, you may choose to use your chosen class prefix (see Item 15) as the private method prefix to greatly reduce the risk of any potential clashes. Similarly, you should consider how other people might subclass your classes. This is why you should use a prefix for private method names. Without the implementation source code, there is no way, except using rather complicated tools, to find out what methods a class implements other than those documented in the public interface definition.

Things to Remember

Prefix private method names so that they are easily distinguished from public methods.

Avoid using a single underscore as the method prefix, since this is reserved by Apple.

Item 21: Understand the Objective-C Error Model

Many modern languages, including Objective-C, have exceptions. If you have come from a Java background, you’ll most likely be accustomed to using exceptions to handle error cases. If you’re used to using exceptions for this task, you are going to have to go back and forget everything you knew about exceptions and start again.

The first thing to note is that Automatic Reference Counting (ARC, see Item 30) is not exception safe by default. In practice, this means that any objects that should be released at the end of a scope in which an exception is thrown will not be released. It is possible to turn on a compiler flag to enable exception-safe code to be generated, but it introduces extra code that has to be run even for the scenario in which no exception is thrown. The compiler flag that turns this on is -fobjc-arc-exceptions.

Even when not using ARC, it is difficult to write code that is safe against memory leaks when exceptions are used. Suppose that a resource is created and needs to be released once it is no longer needed. If an exception is thrown before the resource has been released, that release will never be done:

Click here to view code image

id someResource = /* ... */;
if ( /* check for error */ ) {
    @throw [NSException exceptionWithName:@"ExceptionName"
                                   reason:@"There was an error"
                                 userInfo:nil];
}
[someResource doSomething];
[someResource release];

Of course, the way to solve this problem is to release someResource before throwing; however, if there are many resources to release and more complicated code paths, the code easily becomes cluttered. Also, if something is added to such code, it would be easy to forget to add releases before all times an exception is thrown.

Objective-C has taken the approach recently to save exceptions for the rare scenario in which recovery should be avoided and an exception should cause an application to exit. This means that complex exception-safe code does not need to be involved.

Remembering that exceptions are to be used for fatal errors only, an example of a scenario in which you should consider throwing an exception in your own classes is when creating an abstract base class that should be subclassed before being used. Objective-C has no language construct to say that a class is abstract, unlike some other languages. So the best way to achieve a similar effect is to throw an exception in any method that must be overridden in subclasses. Anyone who then tries to create an instance of the abstract base class and use it will get an exception thrown:

Click here to view code image

- (void)mustOverrideMethod {
    NSString *reason = [NSString stringWithFormat:
                        @"%@ must be overridden",
                        NSStringFromSelector(_cmd)];
    @throw [NSException
        exceptionWithName:NSInternalInconsistencyException
                   reason:reason
                 userInfo:nil];
}

But if exceptions are to be used only for fatal errors, what about other errors? The paradigm chosen by Objective-C to indicate nonfatal errors is either to return nil / 0 from methods where an error has occurred or to use NSError. An example of returning nil / 0 is when in an initializer and an instance cannot be initialized with the parameters passed in:

Click here to view code image

- (id)initWithValue:(id)value {
    if ((self = [super init])) {
        if ( /* Value means instance can't be created */ ) {
            self = nil;
        } else {
            // Initialize instance
        }
    }
    return self;
}

In this scenario, if the if statement determines that the instance can’t be created with the value passed in—maybe value needs to be non-nil itself—self is set to nil, and this is what will be returned. A caller of the initializer will understand that there has been an error, because no instance will have been created.

Using NSError provides much more flexibility because it enables a reason to be given back as to what the error is. An NSError object encapsulates three pieces of information:

Error domain (String)

The domain in which the error occurred. This is usually a global variable that can be used to uniquely define the source of the error. The URL-handling subsystem uses the domain NSURLErrorDomain, for example, for all errors that come from parsing or obtaining data from URLs.

Error code (Integer)

A code that uniquely defines within a certain error domain what error has occurred. Often, an enum is used to define the set of errors that can occur within a certain error domain. HTTP requests that fail might use the HTTP status code for this value, for example.

User info (Dictionary)

Extra information about the error, such as a localized description and another error representing the error that caused this error to occur, to allow information about chains of errors to be represented.

The first way in which errors are commonly used in API design is through the use of delegate protocols. When an error occurs, an object may pass its delegate the error through one of the protocol’s methods. For example, NSURLConnection includes the following method as part of its delegate protocol, NSURLConnectionDelegate:

Click here to view code image

- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error

When a connection decides that there is an error, such as the connection to the remote server times out, this method is called handing an error representing what happened. This delegate method doesn’t have to be implemented, so it is up to the user of the NSURLConnection class to decide it is necessary to know about the error. This is preferable to throwing an exception, since it’s left up to the user to decide whether to be told about the error.

The other common way in which NSError is used is through an out-parameter passed to a method. It looks like this:

- (BOOL)doSomething:(NSError**)error

The error variable being passed to the method is a pointer to a pointer to an NSError. Or you can think of it as a pointer to an NSError object. This enables the method to, in effect, return an NSError object in addition to its return value. It’s used like this:

Click here to view code image

NSError *error = nil;
BOOL ret = [object doSomething:&error];
if (error) {
    // There was an error
}

Often, methods that return an error like this also return a Boolean to indicate success or failure so that you can check the Boolean if you don’t care about what the precise error was or, if you do care, you can check the returned error. The error parameter can also be nil when you don’t care what the returned error is. For instance, you might use the method like this:

Click here to view code image

BOOL ret = [object doSomething:nil];
if (ret) {
    // There was an error
}

In reality, when using ARC, the compiler translates the NSError** in the method signature to NSError*__autoreleasing*; this means that the object pointed to will be autoreleased at the end of the method. The object has to do this because the doSomething: method cannot guarantee that the caller will be able to release the NSError object it created and therefore must add in an autorelease. This gives the same semantics as return values from most methods (excluding, of course, methods that begin with new, alloc, copy, and mutableCopy).

The method passes back the error through the out-parameter like this:

Click here to view code image

- (BOOL)doSomething:(NSError**)error {
    // Do something that may cause an error

    if ( /* there was an error */ ) {
        if (error) {
            // Pass the 'error' through the out-parameter
            *error = [NSError errorWithDomain:domain
                                         code:code
                                     userInfo:userInfo];
        }
        return NO; ///< Indicate failure
    } else {
        return YES; ///< Indicate success
    }
}

The error parameter is dereferenced using the *error syntax, meaning that the value pointed to by error is set to the new NSError object. The error parameter must first be checked to see whether it is non-nil, since dereferencing the null pointer will result in a segmentation fault and cause a crash. Since it is fine for a caller to pass nil, this check must be made for the case that it doesn’t care about the error,

The domain, code, and user information portions of the error object should be set to something that makes sense for the error that has happened. This enables the caller to behave differently, depending on the type of error that has occurred. The domain is best defined as a global constant NSString, and the error codes are best defined as an enumeration type. For example, you might define them like this:

Click here to view code image

// EOCErrors.h
extern NSString *const EOCErrorDomain;

typedef NS_ENUM(NSUInteger, EOCError) {
    EOCErrorUnknown               = –1,
    EOCErrorInternalInconsistency = 100,
    EOCErrorGeneralFault          = 105,
    EOCErrorBadInput              = 500,
};
// EOCErrors.m
NSString *const EOCErrorDomain = @"EOCErrorDomain";

Creating an error domain for your library is prudent, since it allows you to create and return NSError objects that consumers can ascertain came from your library. Creating an enumeration type for the error codes is also a good idea, since it documents the errors and gives the codes a meaningful name. You may also decide to comment the header file where they are defined with even more detailed descriptions of each error type.

Things to Remember

Use exceptions only for fatal errors that should bring down the entire application.

For nonfatal errors, either provide a delegate method to handle errors or offer an out-parameter NSError object.

Item 22: Understand the NSCopying Protocol

A common thing to want to do with an object is to copy it. In Objective-C, this is done through the use of the copy method. The way in which you can support copying of your own classes is to implement the NSCopying protocol, which contains a single method:

- (id)copyWithZone:(NSZone*)zone

This harks back to the day when NSZone was used to segment memory into zones, and objects were created within a certain zone. Nowadays, every app has a single zone: the default zone. So even though this is the method you need to implement, you do not need to worry about what the zone parameter is.

The copy method is implemented in NSObject and simply calls copyWithZone: with the default zone. It’s important to remember that even though it might be tempting to override copy, it’s copyWithZone: that needs to be implemented instead.

To support copying, then, all you need to do is state that you implement the NSCopying protocol and implement the single method within it. For example, consider a class representing a person. In the interface definition, you would declare that you implement NSCopying:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCPerson : NSObject <NSCopying>

@property (nonatomic, copy, readonly) NSString *firstName;
@property (nonatomic, copy, readonly) NSString *lastName;

- (id)initWithFirstName:(NSString*)firstName
            andLastName:(NSString*)lastName;

@end

Then, you would implement the single required method of the protocol:

Click here to view code image

- (id)copyWithZone:(NSZone*)zone {
    EOCPerson *copy = [[[self class] allocWithZone:zone]
                       initWithFirstName:_firstName
                             andLastName:_lastName];
    return copy;
}

This example simply passes all work in initializing the copy to the designated initializer. Sometimes, you might need to perform further work on the copy, such as if other data structures within the class are not set up in the initializer: for example, if EOCPerson contained an array that was manipulated using a couple of methods to befriend and unfriend another EOCPerson. In that scenario, you’d also want to copy the array of friends. Following is a full example of how this would work:

Click here to view code image

#import <Foundation/Foundation.h>

@interface EOCPerson : NSObject <NSCopying>

@property (nonatomic, copy, readonly) NSString *firstName;
@property (nonatomic, copy, readonly) NSString *lastName;

- (id)initWithFirstName:(NSString*)firstName
            andLastName:(NSString*)lastName;

- (void)addFriend:(EOCPerson*)person;
- (void)removeFriend:(EOCPerson*)person;

@end

@implementation EOCPerson {
    NSMutableSet *_friends;
}

- (id)initWithFirstName:(NSString*)firstName
            andLastName:(NSString*)lastName {
    if ((self = [super init])) {
        _firstName = [firstName copy];
        _lastName = [lastName copy];
        _friends = [NSMutableSet new];
    }
    return self;
}

- (void)addFriend:(EOCPerson*)person {
    [_friends addObject:person];
}

- (void)removeFriend:(EOCPerson*)person {
    [_friends removeObject:person];
}

- (id)copyWithZone:(NSZone*)zone {
    EOCPerson *copy = [[[self class] allocWithZone:zone]
                       initWithFirstName:_firstName
                             andLastName:_lastName];
    copy->_friends = [_friends mutableCopy];
    return copy;
}

@end

This time, the copying method has been changed to additionally set the _friends instance variable of the copy to a copy of its own _friends instance variable. Note that the -> syntax has been used here, since the _friends instance variable is internal. A property could have been declared for it, but since it’s never used externally, there is no need to do so.

An interesting question is raised by this example: Why is a copy taken of the _friends instance variable? You could have just as easily not taken a copy, and each object would then share the same mutable set. But that would mean that if a friend were added to the original object, it would also magically become a friend of the copy. That’s clearly not what you would want in this scenario. But if the set were immutable, you might have chosen to not take a copy, since the set cannot change, anyway. This would save having two identical sets lying around in memory.

You should generally use the designated initializer to initialize the copy, just as in this example. But you wouldn’t want to do this when the designated initializer has a side effect that you don’t want to happen to the copy, such as setting up complex internal data structures that you are immediately going to overwrite.

If you look back up to the copyWithZone: method, you will see that the friends set is copied using the mutableCopy method. This comes from another protocol, called NSMutableCopying. It is similar to NSCopying but defines the following method instead:

- (id)mutableCopyWithZone:(NSZone*)zone

The mutableCopy helper is just like the copy helper and calls the preceding method with the default zone. You should implement NSMutableCopying if you have mutable and immutable variants of your class. When using this pattern, you should not override copyWithZone: in your mutable class to return a mutable copy. Instead, if a mutable copy is required of either an immutable or a mutable instance, you should use mutableCopy. Similarly, if an immutable copy is required, you should use copy.

The following holds true in the case of NSArray and NSMutableArray:

Click here to view code image

-[NSMutableArray copy] => NSArray
-[NSArray mutableCopy] => NSMutableArray

Note the subtlety with calling copy on a mutable object and being given an instance of another class, the immutable variant. This is done so that it is easy to switch between mutable and immutable variants. Another way this could have been achieved is to have three methods: copy, immutableCopy, and mutableCopy, where copy always returns the same class, but the other two return specific variants. However, this would not be good if you don’t know whether the instance you have is immutable. You may decide to call copy on something you have been returned as an NSArray but in fact it’s an NSMutableArray. In that case, you would assume that you have an immutable array returned, but instead it’s a mutable one.

You could introspect (see Item 14) to determine what type of instance you have, but that would add complexity everywhere a copy is taken. So you would end up always using immutableCopy or mutableCopy to be on the safe side, in which case, it’s back to just having just two methods, which is exactly the same as having only copy and mutableCopy. The benefit of calling it copy instead of immutableCopy is that NSCopying is designed not only for classes with mutable and immutable variants but also cases in which there is not the distinction, so immutableCopy would be a badly named method.

Another decision to make with your copying method is whether to perform a deep or a shallow copy. A deep copy copies all the backing data as well. Copying by default for all the collection classes in Foundation is shallow, meaning that only the container is copied, not the data stored within the container. This is mainly because objects within the container might not be able to be copied; also, it’s usually not desirable to copy every object. The difference between a deep and a shallow copy is illustrated in Figure 3.2.

Figure 3.2 Shallow versus deep copy. The contents of a shallow copy point to the same objects as the original. The contents of a deep copy point to copies of the original contents.

Usually, you will want your own classes to follow the same pattern as used in the system frameworks, with copyWithZone: performing a shallow copy. But if required, a method can be added to perform a deep copy. In the case of NSSet, this is provided through the following initializer method:

- (id)initWithSet:(NSArray*)array copyItems:(BOOL)copyItems

If copyItems is set to YES, the items in the array are sent the copy message to create a copy to build up the new set to return.

In the example of the EOCPerson class, the set containing the friends is copied in copyWithZone:, but as discussed, this does not copy the items in the set themselves. But if such a deep copy were required, you could provide a method such as the following:

Click here to view code image

- (id)deepCopy {
    EOCPerson *copy = [[[self class] alloc]
                       initWithFirstName:_firstName
                             andLastName:_lastName];
    copy->_friends = [[NSMutableSet alloc] initWithSet:_friends
                                             copyItems:YES];
    return copy;
}

No protocol defines deep copying, so it is left up to each class to define how such a copy is made. You simply need to decide whether you need to provide a deep copy method. Also, you should never assume that an object conforming to NSCopying will be performing a deep copy. In the vast majority of cases, it will be a shallow copy. If you need a deep copy of any object, either find the relevant method, or assume that you have to create your own, unless the documentation states that its implementation of NSCopying is providing a deep copy.

Things to Remember

Implement the NSCopying protocol if your object will need to be copied.

If your object has mutable and immutable variants, implement both the NSCopying and NSMutableCopying protocols.

Decide whether a copy will be shallow or deep, and prefer shallow, where possible, for a normal copy.

Consider adding a deep-copy method if deep copies of your object will be useful.