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