Skip to content
BigZaphod edited this page Apr 7, 2011 · 22 revisions

Code Style Guide

Always keep in mind that this is a framework. Even seemingly small changes can have widespread (and sometimes catastrophic) ramifications in applications that use the framework. Programming within the framework may require a different mindset than programming for the framework.

To keep the project maintainable and easy to approach by newcomers, we need to agree upon at least some rudimentary styles. These aren't necessarily the greatest standards ever, but as long as they are consistent it should make things easier for everyone in the long run.

All indentation should be 4 spaces instead of tabs. This appears to be the Xcode 4 default.

Put the curly braces of method bodies on their own lines, but inline for if/else/etc blocks. There should be a space between the instance/class symbol (+/-) and the return type, but no space between the type and the method name. No spaces between keywords in the method name and their (type)variable parts:

- (void)getLineDash:(CGFloat *)pattern count:(NSInteger *)count phase:(CGFloat *)phase
{
    if (pattern && _lineDashPattern && _lineDashCount > 0) {
        const size_t size = sizeof(CGFloat)*_lineDashCount;
        bcopy(_lineDashPattern, pattern, size);
    }

    if (count) {
        *count = _lineDashCount;
    }
	
    if (phase) {
        *phase = _lineDashPhase;
    }
}

When declaring a property, use this format/spacing around the various elements of the declaration:

@property (nonatomic, readonly, getter=isVisible) BOOL visible;

When synthesizing, I tend to prefer putting them all in a huge block at the top which only gets about as wide as my screen happens to be at the time. I know some people like to give each one their own line which has a logic to it, but can get very tall in some cases. Either way works for me right now. :)

@implementation UIActionSheet
@synthesize delegate=_delegate, destructiveButtonIndex=_destructiveButtonIndex, cancelButtonIndex=_cancelButtonIndex, title=_title;
@synthesize firstOtherButtonIndex=_firstOtherButtonIndex, actionSheetStyle = _actionSheetStyle;

In -init methods, use the following format. I feel it is a compact but visually distinctive way of reminding myself that the -init methods are "different" and worthy of special consideration.

- (id)initWithFrame:(CGRect)frame
{
    if ((self=[super initWithFrame:frame])) {
        _menuTitles = [[NSMutableArray alloc] init];
        _separatorIndexes = [[NSMutableArray alloc] init];
        _destructiveButtonIndex = -1;
        _cancelButtonIndex = -1;
        _firstOtherButtonIndex = -1;
    }
    return self;
}

I strongly prefer that member variables in initializers have default values assigned to them directly rather than using property accessors. My reasoning is that in init the object is not necessarily fully "ready" yet and calling a setter could have unintended side-effects because we cannot know if application code has perhaps subclassed and overridden the setter to do something unexpected. That said, it is not always possible to avoid a setter in an init method - just be aware of the potential for trouble.

In -dealloc it is my position that it is never ever the right thing to call a setter. Release member variables directly. Do not do something like self.property = nil. As rule, you should do as little as possible in -dealloc and calling a setter does not qualify as "little" in my mind. Also remember that under garbage collection, -dealloc is never called. Only use -dealloc to release objects (and remove observers). Setting a member variable to nil after releasing isn't a bad thing, though, even in dealloc as that can aid in debugging. I tend not to do that myself, but it's not a bad idea. :)

For member variables and internal methods, prefix them with an underscore to reduce the chance of conflicting with applications which may subclass framework classes.

If you need to reference private methods from outside of a class implementation, create a UIPrivate category in its own file to keep it out of the public header file. See the other files with private headers to learn the conventions being used in this case.

If you need a non-standard extension to a class, put that interface in an AppKitIntegration category. Again, put this category in its own file and do not include it in any public headers except for AppKitIntegration.h. Keep the default public interface to Chameleon as identical to Apple's interfaces as possible. AppKitIntegration extensions are opt-in by third party apps.

Whenever possible, don't allow AppKit's names to "infect" the Chameleon namespace. Don't include AppKit headers from Chameleon headers. Forward class declarations are okay, but I still like to try to avoid them - although not at the expense of making things painful.

Always import the minimum/most-specific header files necessary to get the job done. Don't do a blanket include of UIKit.h, for example. Often this results in more imports that you may be used to, but it clearly documents dependencies and can reduce compilation time.

Try to avoid forward-declaring methods. If you have to reference a private method in one class from another class, make or import a UIPrivate category header instead. I consider forward declaration of methods to fall under the "don't repeat yourself" agile rule.

Read and apply the Cocoa Coding Guidelines http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html.

Clone this wiki locally