ObjC Coding Style Guide (Version 1.0)
For a compact summary, see the ObjC Coding Style Cheat Sheet.
1. Scope
This guide extends the standard C Coding Style Guide. All C rules remain valid for Objective-C code as well.
This guide covers the Objective-C rules that add to or refine the C rules.
2. Imports and File Structure
Use the normal C include ordering, adapted to Objective-C source files.
Project headers come first. Framework imports come next. C and system headers come last.
Prefer #import for Objective-C headers and @import for frameworks.
Examples:
#import "SettingsWindowController.h"
#import "SettingsWindowSection.h"
@import AppKit;
#include <stdlib.h>
3. Interfaces, Protocols, and Categories
Indent the bodies of @interface, @protocol, and @implementation by one level. This differs intentionally from Apple's default style.
If the superclass does not fit on one line, break before :.
If protocol conformance does not fit on one line, break before < ... >.
Use a space after < and before > in protocol conformance lists so they are not confused with generics.
The normal interface section order is:
- properties
- actions
- initializers
Keep two blank lines between sections.
If sections become large enough that structure would otherwise be unclear, add a marker instead of relying only on blank lines:
// ------------------------------------------------------------------------
// MARK: Section Name
Keep two blank lines before such a marker and one blank line after it. The marker follows the normal indentation of the surrounding @interface or @protocol.
Examples:
@interface Name : Parent
@property(nonatomic,readwrite) NSString * name;
- (void)reload;
@end
@protocol Name < ParentProtocol >
@property(nonatomic,readonly) NSArray <NSString *> * values;
@end
@interface Name (Category)
- (void)reload;
@end
@interface Name
: Parent
@interface Name : Parent
< Protocol1, Protocol2 >
@interface Name : Parent
<
Protocol1, Protocol2,
Protocol3
>
4. Implementations and Ivars
Indent the contents of @implementation by one level. If ivars are declared inside the implementation, indent that block as well.
Ivars always start with _.
Place the ivar block on the next indented level inside @implementation, not flush with the implementation line.
Do not declare explicit ivars or trivial getters just to back normal properties. Prefer the compiler's automatic property synthesis.
If automatic synthesis is not available for a property, for example because the property comes from a protocol, prefer an explicit synthesis:
@synthesize propertyName = _propertyName;
Only write a manual getter or explicit ivar block for a property when the property needs non-trivial behavior or a storage layout that cannot be expressed through normal synthesized properties.
The normal implementation section order is:
- ivars
- deallocator, if present
- properties
- actions
- initializers
- private actions, if present
- overrides, if present
- protocol sections, if present
Protocol sections come after the class's own implementation sections and are grouped by protocol. Within each protocol group, keep the order:
- protocol properties
- protocol actions
- protocol initializers
When a class is small and the sections are obvious, markers are optional.
Keep the normal method spacing from the C guide. Declarations and definitions use spaces inside ( ). Calls do not. The opening { of a method body is on its own line.
Example:
@implementation Name
{
Type * _value;
}
- (Type *)value
{
return _value;
}
- (void)reload
{
}
// --------------------------------------------------------------------
// MARK: Initializers
- (instancetype)initWithValue:(Type *)value
{
self = [super init];
if (!self) return nil;
_value = value;
return self;
}
@end
Bad:
@implementation Name
{
Type * _value;
}
- (void)reload
{
}
@end
5. Properties
Keep short property declarations on one line.
Single-line properties do not need blank lines between them. Use blank lines only to group related properties.
If a property must break, place the type and name on following lines.
If a property declaration is broken across multiple lines, leave one blank line between property declarations. Use two blank lines between property groups.
* belongs to the type, not the variable name.
In implementations, simple property getters belong in the properties section, not in the initializer section.
Properties are normally auto-synthesized. Do not add trivial getters or redundant ivars for them. If synthesis must be made explicit, use @synthesize propertyName = _propertyName;.
Examples:
@property(nonatomic,readwrite) NSString * name;
@property(nonatomic,readonly) NSArray <NSString *> * values;
@property(readwrite)
NSString * name;
@property(atomic,copy)
NSArray <NSString *> *
values;
Good:
NSString *
name;
Bad:
NSString
* name;
6. Generics and Protocol-Qualified Types
Generics use spaces around < and >.
Protocol-qualified object types also use spaces around the protocol list.
The normal pointer spacing rules from the C guide still apply inside generics.
Examples:
NSArray <Type *> * name;
id <SettingsWindowSection> section;
NSArray <id <SettingsWindowSection>> * sections;
7. Method Declarations and Calls
The normal C line-breaking rules still apply.
Do not exceed 80 characters. The line break counts as a character, so the last visible source character may only occupy column 79.
Indentation may decrease by at most one level between adjacent lines.
Break after =.
Break after (, [, or { when those delimiters start a broken expression.
For Objective-C methods and message sends, prefer keeping [ and ] on the same line when the send breaks only once.
There may be up to three arguments on one line for up to two lines. If more than two lines are required, there is one argument per line.
If the message must break more than once, keep the receiver with [ on the first line and continue with selector parts below it.
For long selectors, break along selector parts rather than in the middle of an argument expression whenever possible.
Keep return statements simple, just as in the C guide. Return a simple value, or wrap a more complex expression in ( ).
Examples:
someVarName = [obj someCall:withObject];
someVarName =
[obj someCall:withObject];
someVarName = [obj
someCall:withObject
withSomeOtherParam:paramX];
someVarName = [obj
someCall:withObject
withSomeOtherParam:
[otherObject
someOtherCall
]
];
someVarName = [obj
someCall:withObject
withSomeOtherParam:[otherObject
someOtherCall
]];
NSRect textRect = [attributedString
boundingRectWithSize:
NSMakeSize(CGFLOAT_MAX, drawingRect.size.height)
options:
NSStringDrawingUsesLineFragmentOrigin
| NSStringDrawingUsesFontLeading
];
return (ceil(textRect.size.width) > availableWidth);
8. Blocks
Block type declarations and definitions follow the same spacing rules as functions.
Definitions and declarations use spaces inside ( ). Calls do not. In declarations and definitions there is a space after ^.
Inline block literals do not use a space after ^.
If a block literal fits on one line, it may stay on one line.
If it must break, put { on its own line, like a function body.
If a block has no arguments, write ^( ). Do not split an empty argument list across lines.
When the call ends with the block, }]; may stay together. When the call continues after the block, keep the closing } aligned with the rest of the continued call.
Examples:
void (^ blockName)( arg1, arg2, arg3 );
withCompletion:^int( arg1, arg2 );
andErrorHandler:^( ... ) {
};
withCompletion:^(
arg1, arg2, arg3 )
{
// ...
}];
withCompletion:
^( arg1, arg2, arg3 )
{
// ...
}
andErrorHandler:^(
error )
{
}];
andErrorHandler:^( )
{
}
];
9. Vertical Spacing
Keep two blank lines between method bodies.
Keep three blank lines between method groups, unless a comment marker is used to mark the group. In that case, keep two blank lines before the marker and one blank line after it.
Example:
}
// MARK: Next Group
- (void)nextMethod
10. Consistency Rule
Consistency and readability still win.
If nearby code already establishes a consistent local pattern that follows the rules above, match it. If nearby code violates these rules, follow this guide for new or edited code.