Objective-C Code Standards

From akosma wiki

Jump to: navigation, search

To improve readability and maintainability, the Objective-C code created by akosma software follows these coding standards:

Contents

Files and Code Organization

  • Do not include more than one class in the same file. Use one file per class, with the filename matching the name of the class, for easier retrieval.
  • Use 2- or 3-letter prefixes for classes.
  • Name files with the same name as the class contained in them.
  • Put protocols in a separate file. Do not include protocols in class headers.
  • Lines are indented with 4 spaces, which means NO TABS.
  • Add a space between numbers, mathematical operators and other symbols.
  • Class names use PascalCase, variables and methods use camelCase, constants use ALL_CAPS_WITH_UNDERSCORES.
  • Unless they are assigned some value in the declaration, always initialize all pointer variables to nil, no matter whether they are instance fields or not.
  • Use the @class statement in header files (for both classes and protocols) whenever possible, instead of #import'ing them, to reduce the number of dependencies between files.

Brackets

  • The layout of brackets follows the "Allman" or "ANSI style", with opening bracket in a separate line:
@interface SomeClass : NSObject
{
    // ivars go here
}
  • Always use opening brackets, even in one-line blocks, such as the following if and while statements:
while(x == y)
{
    [something message];
}
[other message];
if(x == y)
{
    [something message];
}

Properties

  • Against Apple's own recommendation, ivars must have an underscore as prefix.
  • Properties have the same name as the ivars they wrap, minus the underscore:
  • Whenever possible, do not specify ivars in the header file; use only @property and @synthesize statements instead.
@interface SomeClass : NSObject

@property (nonatomic) NSInteger ivar;

@end


@implementation SomeClass

@synthesize ivar = _ivar;

@end
  • Do not override @synthesized properties with your own code: use @dynamic properties instead, particularly when you are not wrapping an existing ivar. In those cases, manually add an ivar to the header file.
  • Always use accessors to get or set ivars; do not access them directly. This will make your code KVO- and KVC-compliant, and in Objective-C this is important.
  • To avoid raising KVO notifications during init and dealloc, do not ever use setters or getters in those two methods.
  • In all other methods, always use the setters and getters, to be sure to raise KVO notifications.
  • Append the "IBOutlet" decoration to properties, not to ivars:
@interface SomeClass : NSObject

@property (nonatomic, retain) IBOutlet UILabel *ivar;

@end


@implementation SomeClass

@synthesize ivar = _ivar;

@end
  • Use Accessorizer by Kevin Callahan to generate getters, setters and property declarations.
  • In dealloc, always set variables to nil after releasing them.
  • Use the self.ivar = nil; syntax in other methods. This syntax is the same for retained and assigned properties.
- (id)init
{
    if (self = [super init])
    {
        _ivar = [[SomeClass alloc] init];
    }
    return self;
}

- (void)dealloc
{
    [_ivar release];
    _ivar = nil;

    [super dealloc];
}

- (id)someMethod:(id)param
{
    // ...

    // This generates KVO notifications
    self.ivar = nil;
    
    // ...
    
    return nil;
}

Pointers

  • Pointer variables always feature a space between the class name and the star sign. The star sign and the ivar variable name are not separated by a space:
- (ReturnClass *)methodName:(ParamClass1 *)param1 another:(ParamClass2 *)param2
{
    SomeOtherClass *variable = [[SomeOtherClass alloc] init];
    return nil;
}

Comments

  • Self-documenting code is a myth; always add comments to explain what's going on. More comments is better.
  • Add HeaderDocs (there's a menu in Xcode for that) to class and method definitions. These comments can later be extracted using Doxygen or HeaderDoc:
/**
  First line as abstract comment.
  The rest of the comment is the extended description.
*/
@interface SomeController : UIViewController 
{
}

/**
  First line as abstract comment.
  The rest of the comment is the extended description.
  @return Some float value.
*/
- (float)doSomething;

Protocols

  • Albeit Objective-C is a dynamic language, do not use informal protocols; create explicit files with protocol definitions.
  • Put protocol definitions in their own source code files, never in the same file of the class which uses the protocol methods, neither in the class used as delegate.
  • All protocols must implement the NSObject protocol, to allow for properties of type "id<SomeProtocol>".
  • Follow Apple's guidelines for naming the methods of a protocol; in particular, make sure that the first parameter of every protocol method is a pointer to the object calling the method:
@protocol SomeControllerDelegate <NSObject>

- (void)someController:(SomeController *)controller didSomethingWithThisObject:(id)object;
  • Use the @required and @optional keywords to explicitly separate methods of a protocol which must be implemented from those that should be implemented:
@protocol SomeControllerDelegate  <NSObject>

@required
- (void)someController:(SomeController *)controller didSomethingWithThisObject:(id)object;

@optional
- (void)someControllerDidSomethingElse:(SomeController *)controller;

@end

Before Committing Code in SCM Systems

  • Do not leave compiler warnings unattended. Objective-C code must always compile without warnings -- warnings must be treated as errors.
  • Use the LLVM/Clang Static Analyzer to check your code for memory leaks or unforeseen problems (integrated in Xcode 3.2). Set the "Run Static Analyzer" option for the Debug configuration of your project to make the static analyzer run automatically at each build.
  • Run all unit tests.
  • Always add a meaningful comment with your commit.
Personal tools