Objective-C coding standards. Style

Style

Formatting
SF1. Use appropriate spacing.
Appropriate spacing enhances the readability of lexical elements, so it must be used in all cases. Here is the list of rules with examples: 
  • Do not put space around the primary operators: ., ->, and []
    |
    // Right
    self->URL;
    anObject.URL;
    NSInteger theElement = anArray[theIndex];
    theArray[0] = 1;

    // Wrong
    self-> URL;
    anObject. URL;
    self -> URL;
    anObject .URL;
    theArray [0] = 1;
    self.title = aStrings [ theIndex ];
  • Put a space before parentheses, but not following method names
    | // Right
    CGFloat theMinX = CGRectGetMinX(theFrame);
    if (theMinX > 100.0f)
    {
    //...
    for (NSUInteger i = 0; i < theCount; ++i)
    {
    //...


    // Wrong
    CGFloat theMinX = CGRectGetMinX (theFrame);
    if(theMinX > 100.0f)
    {
    //...

    for(NSUInteger i = 0; i < theCount; ++i)
    {
    //...

    * Do not put spaces between unary operators and their operands
    | // Right
    if (!thePointer && !(theNewValue || theValueDifference))
    {
       return ++i;


    // Wrong
    if (! theValue && theIndex ++)
    {
       return ( & theObject );

    * Put spaces around assignment operators
    | // Right
    theCurrentIndex = theValue + 1;
    theCounter += 1;

    // Wrong
    theCurrentIndex =theValue + 1;
    theCounter+= 1;
    theObjectIndex=[theObjects indexOfObject:anObject];
  • Put spaces around *conditional operators*
    | // Right
    x = (a > b) ? c : d;

    // Wrong
    x = (a >b)? c : d;
  • Comma and semicolon are to be followed by one space (or a new line), but there is no space before it
    | // Right
    void doSomething(NSInteger aLength, NSInteger aMaxLength, NSInteger aCount)
    {
        //...

    theCount = [self count];
    for (NSInteger i = 0; i < theCount; ++i)
    {
       doSomething(i, [self maxLength], theCount);


    // Wrong
    void doSomething(NSInteger aLength ,NSInteger aMaxLength,NSInteger aCount)
    {
       //...

    theCount = [self count] ;
    for (NSInteger i = 0 ; i < theCount;++i)
    {
       doSomething(i , [self maxLength], theCount) ;

    * Put one space on both sides ofother operators
    | // Right
    z = x + y;
    flag = flag1 && flag2;

    // Wrong
    x = u*sizeof(NSUInteger);
    x/=2
  • When declaring pointer variables * is appended to the variable name
    |
    // Right
    NSString *theTitle = nil;
    - (id)titleWithString:(NSString *)aString;
    static NSString *const KHPLTitle = @"title";

    // Wrong
    NSString* theTitle = nil;
    NSString * theTitle = nil;
    - (id)titleWithString:(NSString*)aString;
    static NSString* const KHPLTitle = @"title";
Status: Rule


SF2. Use stand alone braces to guard blocks of code.
Compound statements, also known as blocks, are lists of statements enclosed in braces. Braces are to stand alone, or in other words they are to be placed on separate lines and aligned with their contents indented by one tab. 
Example: 
// Right: Stand alone braces are used correctly
if (nil != theObject)
{
   theIndex += 2;

   // Wrong
  if (!thePointer) {
   while (theIndex < 10) { theIndex += 2; thePointer++; }


Although C and Objective-C do not require braces around single statements, braces are to be used for single statement blocks to help improve the readability and maintainability of the code. If braces are not used in single statement blocks the risk of maintenance errors gets increased. Maintenance may cause adding a statement within the block, but an absence of braces leads to unexpected results. 

Because the else part of an if-else statement is optional, omitting the 'else' from a nested if sequence can result in ambiguity. Therefore, always use braces to avoid confusion and to make certain that the code compiles the way it was intended. 

Example: 
// Right: Used braces allow to avoid ambiguity 
if (self.connected)
{
   for (NSInteger i = 0; i < theCount; ++i) 
   { 
      if ([[anElements objectAtIndex:i] integerValue] > 0) 
      {
         [self addElement:[anElements objectAtIndex:i]]; 
      } 
   } 

else // Right: braces force proper association 
{ 
   DLog(@"Error: not connected."); 

// Wrong 
if (self.connected)
for (NSInteger i = 0; i < theCount; ++i) 
if ([[anElements objectAtIndex:i] integerValue] > 0) 
{
   [self addElement:[anElements objectAtIndex:i]]; 
else // Wrong: the compiler will match to closest if-else 
  DLog(@"Error: not connected.");

If a loop statement has a dummy body, opening and closing brackets are to be added on separate lines. It is a good practice to add a comment stating that the dummy body is deliberate. 
Example: 
// Right: Stand alone braces are used correctly 
while (nil != [[self enumerator] nextObject]) 
   // Do nothing 
}

Exceptions: 
The only exception is a do {} while (...) statement. 
// Right: Stand alone braces are not applicable in this case 
do 
   // ... 
} while (0);

Status: Rule


SF3. Tabs must always be set to 3 spaces. Use tabs for indenting, not spaces. Disable line wrapping and syntax-aware indenting.
Set “Prefer ident using”, “Tab width”, “Indent width”, “Tab key”, “Line wrapping” and “Syntax-aware indenting” settings in XCode exactly as on screenshot above. 
Status: Rule


SF4. Limit lines in source files to 80 characters.
Set “Page guide at column” setting in XCode exactly as on screenshot above. 
Only when source lines exceed the length of 80 characters, break the code into multiple lines, and indent the continuation lines one tab (not white space!) past the indentation level of the first line, or more if and only if it is logically associated with something later on the line above. In any case try to fill the line as long as possible without separations.
Line can exceed length 80 chars in cases:
a) line exceeds the limit only a few characters;
b) to separate line we should brake a short term. 
Example: 
// Right: The following is separated correctly
- (void)composeMailMessage
{
   MFMailComposeViewController *theController = [[MFMailComposeViewController 
      alloc] init];
   if (nil != theController)
   {
      theController.mailComposeDelegate = self;
      [theController setSubject:[NSString stringWithFormat:MPXLocalizedString(
         @"Activation Code for %@"), [[[NSBundle mainBundle] infoDictionary] 
         objectForKey:@"CFBundleDisplayName"]]];
      [theController setMessageBody:self.activationCode isHTML:NO];
      [[[[UIApplication sharedApplication] keyWindow] rootViewController] 
      presentModalViewController:theController animated:YES];
      [theController release];
   }

// Wrong: Never do the following 
- (void)composeMailMessage
{
   MFMailComposeViewController *theController = 
                                    [[MFMailComposeViewController alloc] 
init];
   if (nil != theController)
   {
      theController.mailComposeDelegate = self;
      [theController setSubject:
      [NSString stringWithFormat:
                   MPXLocalizedString(@"Activation Code for %@"), 
                          [[[NSBundle mainBundle] infoDictionary] 
                            objectForKey:@"CFBundleDisplayName"]]];
      [theController setMessageBody:self.activationCode 
                 isHTML:NO];
      [[[[UIApplication sharedApplication] keyWindow] 
         rootViewController] 
                      presentModalViewController:theController 
                                                 animated:YES];
      [theController release];
   }

Status: Rule 




SF5. Function and method names are to be written in one line with their return type. 

Status: Rule



SF6. Function and method parameter names are to be written in one line with their type. 

Status: Rule


Declaration and Initialization 

SD1. It is not allowed more than one declaration in one line. 

More than one declaration in the single line may provoke mistakes, incorrect interpretation, and significantly reduced readability of the code, and thus it's forbidden.

Example:
| // Right: The following is correct, moreover it allows to avoid mistakes in declaration
char *theString = "This is a string";
char *theBuffer = NULL;

// Wrong: The following is not allowed, as a result of incorrect declaration 'buffer'
// has an incorrect type
char *theString = "This is a string", theBuffer = NULL;

Status: Rule


SD2. All variables must be initially initialized.
  • All local variables must be initially initialized in place
    |
    // Right: This one is correct
    void *thePointer = NULL;
    // ...

    // Wrong: It's not allowed to use uninitialized local variables
    void *thePointer;
    // ...
    if (thePointer)
    {
       //...
    * There is no exception for built-in types
    | // Right: This one is correct
    int theIndex = 0;

    // Wrong: It's not allowed to use uninitialized variables of built-in types
    int theIndex;
  • Initialize variables with a struct type with (0)
    | struct HPLFoo
    {
       // ...

       // Right: This one is correct
       HPLFoo theFoo = (0}
       // Wrong: It's not allowed to use not initialized variables
       HPLFoo theFoo;
       ... |
Exceptions: 
It's not required to initialize member variables of Objective-C class with their default values since they are initialized automatically. 
Status: Rule


SD3. Use named enumerations with the directly initialized first value.
Name of the enumeration begins with a single uppercase letter, it might be a good idea to use corresponding prefix that identifies it. To avoid potential name clashes, it's best to declare the enum inside of the class that 'owns' it. Each enumerated value must have a unique name, and usage of unnamed enumerations are not allowed. 
// Right: The following enumeration is declared correctly
enum HPLNotifications
{
   kHPLSendNotification = 0,
   kHPLGetNotification // Note, no comma goes here

   // Wrong: Name starts with a lowercase letter 
   enum kNotifications
   {
      sendNotification, // Wrong: The first value is not initialized
      getNotification // Wrong: Name does not start with 'k' prefix (see NP4)

Status: Rule 




SD4. Include meaningful formal argument names in function declarations. 

Although they are not compulsory, dummy arguments improves a lot the understanding and use of the class interface, they make it more clear. The argument names may be skipped in the implementation if they are not used in body of method, just to underline that fact, but it's not required.

Status: Rule



SD5. Names of formal arguments used in function declarations are to be the same as actual arguments in function implementation. 

Status: Rule



SD6. In Objective-C method declarations there must be a space after – or + and space or newline after each two different parameters. There must be no other spaces in method declarations excluding pointers in braces. 

Example:
| // Right
- (void)setValue:(NSValue *)aValue updateNodes:(BOOL)aFlag;
- (BOOL)moveToPoint:(NSPoint)aPoint error:(NSError **)anError;

// Wrong
- (BOOL) updateWithRect: (NSRect)aRect value: (NSError**) anError;
-(void)setValue:(NSValue*) aValue;

Status: Rule


SD7. In Objective-C method calls, there should be no white spaces between parameter name, colon, and parameter values.
Example: 
[theWindow setFrame:theRect display:YES];

Status: Rule


SD8. In variable declarations of type conforming to protocol, there must be no space between type and protocol.
Example: 
id<NSCoding> theObject = nil; 
NSCell<NSTextAttachmentCell> *theCell = nil;

Status: Rule


SD9. Use NULL, nil, and Nil for pointers to corresponding entities only.
It's important to initialize a corresponding entity correctly. Here is a list of rules:
  • NULL must be used to initialize raw pointers to C/C++ objects only
  • nil must be used to initialize pointers to Objective-C types only
  • Nil must be used to initialize pointers to Objective-C classes only 
Example: 
// Right
HPLFoo *theFoo = NULL; // HPLFoo is a structure
id theObject = nil;
Class *theClass = Nil;
SEL theSelector = NULL;

// Wrong
HPLFoo *theFoo = nil; // HPLFoo is a structure
NSInteger *theCounter = Nil;
NSObject *theObject = NULL;
NSInteger theFlag = NULL;

Status: Rule


SD10. Use YES and NO when dealing with BOOL type.
Status: Rule

Comments
SC1. All comments must be written in complete (short and expressive) English sentences.
The quality of the comments is an important factor for the understanding of the code as a whole, so requirements for their clarity and understandability are strong. 
Status: Rule


SC2. In implementation file, above method implementation a comment describing what the method does, how it does it and optionally preconditions and postconditions, may be specified if needed.
If a particular function or method is not unique or its implementation is obvious, don't add this section. 
Status: Recommendation


SC3. Do not explain in comments what is done, but why it is done and if it is not obvious only.
Comments are to be used for clarification purpose only, they must be considered inapplicable if they prevent a comprehension of particular code. 
Status: Recommendation


SC4. Use // for comments.
The C-like comments /.../ do not nest; therefore they lead to problems if by accident they appear nested. Alternatively for quick commenting and removing comments from a particular block of code the #if 0 // (... #endif // } construction may be used. 
Status: Recommendation


SC5. Use TODO for those parts of code which require finalization, improvement, or further review.
This consideration helps to locate such parts easily by just by specifying TODO as a search string. 
Status: Recommendation

Organization of Files
SO1. Use templates for source files instead of creating your own ones.
The usage of templates significantly decreases customization of file organization, and thus make sources uniquely organized. For additional information refer to: TBA 
Status: Rule


SO2. Sections in the file are ordered as following: included files, declarations of constants, macros, and types, forward declarations. Sections are separated by lines.
This makes easier to read your source code files, since corresponding sections appear in expected order. 
Example: 
//////////////////////////////////////////////////////////////////////////////// 
#import "HPLSimpleRequest.h" 
#import "IHPLImageRequest.h" 

//////////////////////////////////////////////////////////////////////////////// 
extern const NSUInteger kHPLMaxWidth; 

//////////////////////////////////////////////////////////////////////////////// 
@protocol IHPLImageProperties; 

//////////////////////////////////////////////////////////////////////////////// 
@interface HPLImageRequest : HPLSimpleRequest <IHPLImageRequest> 

@property (nonatomic, retain) id<IHPLImageProperties> properties; 
//... 

@end

Status: Recommendation


SO3. Each file must contain a header with correct copyrights, years, its name, and author identity.
For additional information refer to file templates (see TBA). 
Status: Rule


SO4. Organize files following the principle: 'most important goes first'.
It's important to organize file that way the most significant information goes at first followed by less significant. This may dramatically increase readability of source code as well as make it easy to understand. 
Status: Rule


SO5. Keep the ordering of methods in the header file and in the source files identical.
This facilitates the readability of implementation of classes and lets to find a necessary method quickly at the expected position. 

Status: Rule