CocoaDevCentral.com . Articles . Cocoa Style for Objective-C: Part II Email Feedback
C Language Tutorial for Cocoa

Objective-C File Icon
In a nutshell: how Cocoa and Objective-C code should look

Once you've figured out the basics of Objective-C and Cocoa, you're ready to start writing some code. But the conventions of naming and formatting Objective-C code are not the same as traditional C, C++ or even Java programs.

Apple has laid out a set of guidelines as to how code should be written for maximum clarity and integration with the frameworks. In addition, there are some undocumented conventions that Cocoa developers often use.

In essence, the human factor present in Apple's products for the end user can be found in Objective-C and Cocoa themselves.

Part 1: basics on naming classes, variables, accessors, general methods and abbreviations.
Part 2: more detail on method names, global symbols, the id type, method parameters, etc

1 of 8

Method Names: Returning Objects

In addition to simple accessors, classes or objects can also return objects based on various conditions or input. The format is simple:

[object/class thing+condition]; [object/class thing+input:input]; [object/class thing+identifer:input];

Examples
realPath = [path stringByExpandingTildeInPath]; fullString = [string stringByAppendingString:@"Extra Text"]; object = [array objectAtIndex:3]; // class methods newString = [NSString stringWithFormat:@"%f",1.5]; newArray = [NSArray arrayWithObject:newString];

If I wrote some of my own, this is what they might look like.

recipients = [email recipientsSortedByLastName]; newEmail = [CDCEmail emailWithSubjectLine:@"Extra Text"]; emails = [mailbox messagesReceivedAfterDate:yesterdayDate];

Note that all of these messages first indicate what kind of thing will be returned, followed by what the circumstances will be for returning it. Also note that the last word right before the colon describes the type of the supplied argument.

Sometimes, you want a variation on a value. In that case, the format is generally:

[object adjective+thing]; [object adjective+thing+condition]; [object adjective+thing+input:input];

Examples
capitalized = [name capitalizedString]; rate = [number floatValue]; newString = [string decomposedStringWithCanonicalMapping]; subarray = [array subarrayWithRange:segment];

Messages are rarely quite as long as -decomposedStringWithCanonicalMapping

2 of 8

Avoid Ambiguity

Bugs are scarce where code doesn't leave questions unanswered.

Ambiguous Messages
-sortInfo -refreshTimer -update -fetchInfo:

On the surface, these methods may seem good. For example, they all have vowels. But what they share is the potential for different interpretations because of the language used.

This is all fixed by slightly modifying the phrases:

Clear Messages
-currentSortInfo // "current" obviously describes the noun "sort info" -refreshDefaultTimer // refresh is now clearly a verb -updateMenuItemTitle // an action is taking place -infoForFetch: // now we know info is returned for a fetch

By just adding a few characters to each method, we've removed almost all ambiguity. And there was much rejoicing.

Note that the -updateMenuItem method doesn't put the NS prefix on menu item

3 of 8

Global C Functions

Global C functions generally use one of a few simple formulas:

Prefix + Value () Prefix + Value + With/From/For + Input () Prefix + Action () Prefix + Action + Type ()

Just like classes, functions are prefixed with initials in order to prevent namespace issues. Since C functions are free-standing by nature, the function name needs to indicate data types they interact with, if any.

Functions from Cocoa
NSHomeDirectory() NSHomeDirectoryForUser() NSClassFromString() NSBeginAlertSheet() NSDrawGrayBezel()

Core Services Functions

In Core Services frameworks such as Core Foundation and Core Graphics, functions are prefixed with the most-relevant opaque type, and the "get" prefix is used even when there's no indirection involved:

Core Foundation
CFArrayGetValueAtIndex() // returned directly, but "get" is still used CFDictionaryGetValue() CFDateGetAbsoluteTime()

Core Graphics / Quartz
CGImageCreate() CGImageGetHeight() CGImageGetTypeID()

4 of 8

Other Global Symbols

There are several types of symbols with global scope in addition to C functions. For example:

Protocols, constants, structs, enums and enum values are basically named according to the same rules as classes or C functions. Capitalized with initials at the front:

Structs
NSPoint point; // struct NSRange range; // struct NSRectArray * rects; // c-style array of structs

In Cocoa, enums are frequently used as "modes" for methods:

range = [string rangeOfString:@"find me" options:NSLiteralSearch];

Both constants and enums have a suffix that indicates what kind of thing they are:

Constants and Enums
// search modes (enums) NSLiteralSearch NSCaseInsensitiveSearch // exception names (constants) NSMallocException NSInvalidArgumentException // notification names (constants) NSTaskDidTerminateNotification NSWindowWillMoveNotification

Also, note that notification names have a slightly different formula:

Class of Affected Object + Did/Will + Action + "Notification"

5 of 8

Dynamic Typing

Objective-C is a dynamically-typed language, meaning that you don't have to tell the compiler what type of object you're working with at compile time.

Declaring a type for a varible is merely a promise which can be broken at runtime if the code leaves room for such a thing. You can declare your variables as type id, which is suitable for any Objective-C object.

Dynamically-Typed Variables
id hostName; id ipAddress; id keyedAccountNames; id theObject; // the compiler is fine with this theObject = [NSString string]; theObject = [NSNumber numberWithInt:1]; theObject = [NSDictionary dictionary];

So why specify type at all? Three basic reasons:

  1. To be clear: Makes it clear what you intend to do with the variable
  2. To avoid useless warnings: If multiple classes share the same method name, the compiler may warn you when you send that message to a generic object.
  3. To get useful warnings: If you mispell a message name, such as "-stringg", the compiler will tell you that NSMutableString does not implement such a method

In addition, there are situations where the id type makes the most sense. Some are:

  1. A delegate or datasource
  2. Object for a notification
  3. Contents for a generic container
  4. Objects involved in target/action

So no hard rules here, but a good basic practice is to specify the type if you have reason to believe other types of objects wouldn't make sense in a given situation.

6 of 8

When to Use Accessors

Steps Inside a Setter

Short answer: always

Why not just directly access instance variables within a class? It's a lot less code, right?

The reason is flexibility. If your code gets to data via accessors, it's easy to change how that data is manipulated later.

For example, it gives you a good entry point for registering the previous value with NSUndoManager. Or when debugging, it might help to log when a particular instance variable is fetched.

But there's an even better reason to create accessors: Key-Value Coding. KVC is a protocol used throughout Cocoa, most notably in bindings. It will look for accessors for your keys first, and only access data directly as a last resort. You can shorten KVC's search and thus speedup data access by implementing accessors.

Also be aware that if you set instance variables directly, in the form of var = value, Key-Value Observing will not notice the change and bound objects will not get the new value.

7 of 8

Naming Parameters

Let's take a quick visit to method parameters. What's the standard here? The guidelines are considerably more loose, but typically you prefix the input name with "the", "an" or "new"

Prefixes for Method Parameters
- (void) setTitle: (NSString *) aTitle; - (void) setName: (NSString *) newName; - (id) keyForOption: (CDCOption *) anOption - (NSArray *) emailsForMailbox: (CDCMailbox *) theMailbox; - (CDCEmail *) emailForRecipients: (NSArray *) theRecipients;

Also worth noting is the naming convention for a loop. Typically, the current object in the loop is prefixed with "one" or "a/an". Some also simply refer to the individual object as "item":

Variable Names in Loops
for (i = 0; i < count; i++) { oneObject = [allObjects objectAtIndex: i]; NSLog (@"oneObject: %@", oneObject); } NSEnumerator *e = [allObjects objectEnumerator]; id item; while (item = [e nextObject]) NSLog (@"item: %@", item);

8 of 8

Odds and Ends

If you're sending a message with a particularly long name, break it up into multiple lines:

Splitting Up Long Message Names
color = [NSColor colorWithCalibratedHue: 0.10 saturation: 0.82 brightness: 0.89 alpha: 1.00];

Classes that return one and only one instance of themselves (singletons) are named and implemented as follows:

Singleton
@implementation CDCMailboxManager + (id) sharedMailboxManager { static CDCMailboxManager * shared = nil; if ( !shared ) shared = [[self alloc] init]; return shared; }

Wrap Up

Assuming you've already read Part I, you should be fully-equipped to go out and start writing code that looks and feels like Cocoa itself. If you hunger for even more style, be sure to check out Apple's coding guidelines in the links list below.

As always, let us know what you think about the tutorial.


Further Reading

Local Page Cocoa and Objective-C Style: Part I first part of this tutorial
Apple Cocoa Guidelines the authorative documents on coding guidelines for Cocoa
Apple Objective-C Naming a short summary of Apple's conventions for the language