Revision 2.52
Hooray! Now you know you can expand points to get more details. Alternatively, there's an "expand all" at the top of this document.
Objective-C is a very dynamic, object-oriented extension of C. It's designed to be easy to use and read, while enabling sophisticated object-oriented design. It is the primary development language for new applications on Mac OS X and the iPhone.
Cocoa is one of the main application frameworks on Mac OS X. It is a collection of Objective-C classes that provide for rapid development of full-featured Mac OS X applications.
Apple has already written a very good, and widely accepted, coding guide for Objective-C. Google has also written a similar guide for C++. This Objective-C guide aims to be a very natural combination of Apple's and Google's general recommendations. So, before reading this guide, please make sure you've read:
Note that all things that are banned in Google's C++ guide are also banned in Objective-C++, unless explicitly noted in this document.
The purpose of this document is to describe the Objective-C (and Objective-C++) coding guidelines and practices that should be used for all Mac OS X code. Many of these guidelines have evolved and been proven over time on other projects and teams. Open-source projects developed by Google conform to the requirements in this guide.
Google has already released open-source code that conforms to these guidelines as part of the Google Toolbox for Mac project (abbreviated GTM throughout this document). Code meant to be shared across different projects is a good candidate to be included in this repository.
Note that this guide is not an Objective-C tutorial. We assume that the reader is familiar with the language. If you are new to Objective-C or need a refresher, please read The Objective-C Programming Language .
They say an example is worth a thousand words so let's start off with an example that should give you a feel for the style, spacing, naming, etc.
An example header file, demonstrating the correct commenting and spacing
for an @interface
declaration
An example source file, demonstrating the correct commenting and spacing
for the @implementation
of an interface. It also includes the
reference implementations for important methods like getters and setters,
init
, and dealloc
.
Blank lines before and after @interface
,
@implementation
, and @end
are optional. If your
@interface
declares instance variables, a blank
line should come after the closing brace (}
).
Unless an interface or implementation is very short, such as when declaring a handful of private methods or a bridge class, adding blank lines usually helps readability.
We use spaces for indentation. Do not use tabs in your code. You should set your editor to emit spaces when you hit the tab key.
Strive to keep your code within 80 columns. We realize that Objective C is a verbose language and in some cases it may be more readable to extend slightly beyond 80 columns, but this should definitely be the exception and not commonplace.
If a reviewer asks that you reformat a line because they feel it can be fit in 80 columns and still be readable, you should do so.
We recognize that this rule is controversial, but so much existing code already adheres to it, and we feel that consistency is important.
You can make violations easier to spot in Xcode by going to Xcode > Preferences > Text Editing > Show page guide.
-
or +
and the return type, and no spacing in the parameter list except between
parameters.
Methods should look like this:
The spacing before the asterisk is optional. When adding new code, be consistent with the surrounding file's style.
If you have too many parameters to fit on one line, giving each its own line is preferred. If multiple lines are used, align each using the colon before the parameter.
When the first keyword is shorter than the others, indent the later lines by at least four spaces, maintaining colon alignment:
Invocations should have all arguments on one line:
or have one argument per line, with colons aligned:
Don't use any of these styles:
As with declarations and definitions, when the first keyword is shorter than the others, indent the later lines by at least four spaces, maintaining colon alignment:
@public
and @private
access modifiers
should be indented by 1 space.
This is similar to public
, private
, and
protected
in C++.
@
label on its own line and a
space between the @
label and the opening brace
({
), as well as between the @catch
and the
caught object declaration.
If you must use Obj-C exceptions, format them as follows. However, see Avoid Throwing Exceptions for reasons why you should not be using exceptions.
This applies to class declarations, instance variables, and method declarations. For example:
There are several appropriate style rules, depending on how long the block is:
^{
. If the block takes parameters, there is no
space between the ^(
characters, but there is one space
between the ) {
characters.
Naming rules are very important in maintainable code. Objective-C method names tend to be very long, but this has the benefit that a block of code can almost read like prose, thus rendering many comments unnecessary.
When writing pure Objective-C code, we mostly follow standard Objective-C naming rules. These naming guidelines may differ significantly from those outlined in the C++ style guide. For example, Google's C++ style guide recommends the use of underscores between words in variable names, whereas this guide recommends the use of intercaps, which is standard in the Objective-C community.
Any class, category, method, or variable name may use all capitals for initialisms within the name. This follows Apple's standard of using all capitals within a name for initialisms such as URL, TIFF, and EXIF.
When writing Objective-C++, however, things are not so cut and dry. Many projects need to implement cross-platform C++ APIs with some Objective-C or Cocoa, or bridge between a C++ back-end and a native Cocoa front-end. This leads to situations where the two guides are directly at odds.
Our solution is that the style follows that of the method/function being
implemented. If you're in an @implementation
block, use the
Objective-C naming rules. If you're implementing a method for a C++
class
, use the C++ naming rules. This avoids the situation
where instance variable and local variable naming rules are mixed within a
single function, which would be a serious detriment to readability.
File extensions should be as follows:
.h |
C/C++/Objective-C header file |
.m |
Objective-C implementation file |
.mm |
Objective-C++ implementation file |
.cc |
Pure C++ implementation file |
.c |
C implementation file |
File names for categories should include the name of the class being
extended, e.g. GTMNSString+Utils.h
or
GTMNSTextView+Autocomplete.h
In order to minimize clashes between the differing naming styles when
mixing Cocoa/Objective-C and C++, follow the style of the method being
implemented. If you're in an @implementation
block, use
the Objective-C naming rules. If you're implementing a method for a
C++ class
, use the C++ naming rules.
In application-level code, prefixes on class names should
generally be avoided. Having every single class with same prefix
impairs readability for no benefit. When designing code to be shared
across multiple applications, prefixes are acceptable and recommended
(e.g. GTMSendMessage
).
For example, if we want to create a category on NSString
for parsing, we would put the category in a file named
GTMNSString+Parsing.h
, and the category itself would be
named GTMStringParsingAdditions
(yes, we know the file
name and the category name do not match, but this file could have many
separate categories related to parsing). Methods in that category
should share the prefix (gtm_myCategoryMethodOnAString:
)
in order to prevent collisions in Objective-C which only has a single
namespace. If the code isn't meant to be shared and/or doesn't run in
a different address-space, the method naming isn't quite as
important.
There should be a single space between the class name and the opening parenthesis of the category.
The method name should read like a sentence if possible, meaning you
should choose parameter names that flow with the method name. (e.g.
convertPoint:fromRect:
or
replaceCharactersInRange:withString:
). See Apple's
Guide to Naming Methods for more details.
Accessor methods should be named the same as the variable they're
"getting", but they should not be prefixed with the word
"get". For example:
This is for Objective-C methods only. C++ method names and functions continue to follow the rules set in the C++ style guide.
Do not use Hungarian notation for syntactic attributes, such as the static type of a variable (int or pointer). Give as descriptive a name as possible, within reason. Don't worry about saving horizontal space as it is far more important to make your code immediately understandable by a new reader. For example:
Instance variables are mixed case and should be prefixed with an underscore e.g. _usernameTextField. Note that historically the convention was to put the underscore at the end of the name, and projects may opt to continue using trailing underscores in new code in order to maintain consistency within their codebase (see the Historical Notes section). It is recommended you leave old code as-is, unless doing so would create inconsistency within a class.
Constant names (#defines, enums, const local variables, etc.) should start with a lowercase k and then use mixed case to delimit words, i.e. kInvalidHandle, kWritePerm.
Though a pain to write, they are absolutely vital to keeping our code readable. The following rules describe what you should comment and where. But remember: while comments are very important, the best code is self-documenting. Giving sensible names to types and variables is much better than using obscure names and then trying to explain them through comments.
When writing your comments, write for your audience: the next contributor who will need to understand your code. Be generous—the next one may be you!
Remember that all of the rules and conventions listed in the C++ Style Guide are in effect here, with a few additional points, below.
Every file should contain the following items, in order:
If you make significant changes to a file with an author line, consider deleting the author line since revision history already provides a more detailed and accurate record of authorship.
If you have already described an interface in detail in the comments at the top of your file feel free to simply state "See comment at top of file for a complete description", but be sure to have some sort of comment.
Additionally, each method in the public interface should have a comment explaining its function, arguments, return value, and any side effects.
Document the synchronization assumptions the class makes, if any. If an instance of the class can be accessed by multiple threads, take extra care to document the rules and invariants surrounding multithreaded use.
This helps eliminate ambiguity, especially when the symbol is a common word that might make the sentence read like it was poorly constructed. E.g. for a symbol "count":
or when quoting something which already contains quotes
Instance variables which are pointers to objects derived from NSObject are presumed to be retained, and should be either commented as weak or declared with the __weak lifetime qualifier when applicable. Similarly, declared properties must specify an assign property attribute if they are not retained by the class. An exception is instance variables labeled as IBOutlets in desktop Mac software, which are presumed to not be retained.
Where instance variables are pointers to Core Foundation, C++, and other non-Objective-C objects, they should always be declared with the __strong or __weak type modifiers to indicate which pointers are and are not retained. Core Foundation and other non-Objective-C object pointers require explicit memory management, even when building for automatic reference counting or garbage collection. When the __weak type modifier is not allowed (e.g. C++ member variables when compiled under clang), a comment should be used instead.
Be mindful that support for automatic C++ objects encapsulated in Objective-C objects is disabled by default, as described here.
Examples of strong and weak declarations:
Object ownership and lifetime are explicit when using ARC, so no additional comments are required.
@private
when they are
declared in a header file.
It is important for those who might be subclassing your class that the designated initializer be clearly identified. That way, they only need to subclass a single initializer (of potentially several) to guarantee their subclass' initializer is called. It also helps those debugging your class in the future understand the flow of initialization code if they need to step through it.
init...
method,
make sure you override the superclass' designated initializer.
If you fail to override the superclass' designated initializer, your initializer may not be called in all cases, leading to subtle and very difficult to find bugs.
NSObject
at the top of an
@implementation
.
init...
,
copyWithZone:
, and dealloc
methods.
init...
methods should be grouped together, followed by
the copyWithZone:
method, and finally the
dealloc
method.
0
or nil
in the
init method; it's redundant.
All memory for a newly allocated object is initialized to 0 (except
for isa), so don't clutter up the init
method
by re-initializing variables to 0 or nil
.
NSObject
class method new
,
nor override it in a subclass. Instead, use alloc
and
init
methods to instantiate retained objects.
Modern Objective-C code explicitly calls alloc
and an
init
method to create and retain an object. As the
new
class method is rarely used, it makes reviewing code
for correct memory management more difficult.
Unlike C++, Objective-C doesn't have a way to differentiate between public and private methods—everything is public. As a result, avoid placing methods in the public API unless they are actually expected to be used by a consumer of the class. This helps reduce the likelihood they'll be called when you're not expecting it. This includes methods that are being overridden from the parent class. For internal implementation methods, use a category defined in the implementation file as opposed to adding them to the public header.
Before Objective-C 2.0, if you declare a method in the private
@interface
, but forget to implement it in the main
@implementation
, the compiler will not object.
(This is because you don't implement these private methods in a
separate category.) The solution is to put the functions within
an @implementation
that specifies the category.
If you are using Objective-C 2.0, you should instead declare your private category using a class extension, for example:
which will guarantee that the declared methods are implemented in the
@implementation
section by issuing a compiler warning if
they are not.
Again, "private" methods are not really private. You could accidentally override a superclass's "private" method, thus making a very difficult bug to squash. In general, private methods should have a fairly unique name that will prevent subclasses from unintentionally overriding them.
Finally, Objective-C categories are a great way to segment a large
@implementation
section into more understandable chunks
and to add new, application-specific functionality to the most
appropriate class. For example, instead of adding "middle truncation"
code to a random object in your app, make a new category on
NSString
).
#import
Objective-C/Objective-C++ headers, and
#include
C/C++ headers.
Choose between #import
and #include
based
on the language of the header that you are including.
#import
.#include
. The header should provide its own #define
guard.
Some Objective-C headers lack #define
guards, and expect
to be included only by #import
. As Objective-C headers
may only be included in Objective-C source files and other Objective-C
headers, using #import
across the board is appropriate.
Standard C and C++ headers without any Objective-C in them can expect
to be included by ordinary C and C++ files. Since there is no
#import
in standard C or C++, such files will be
included by #include
in those cases. Using
#include
for them in Objective-C source files as well
means that these headers will always be included with the same
semantics.
This rule helps avoid inadvertent errors in cross-platform
projects. A Mac developer introducing a new C or C++ header might
forget to add #define
guards, which would not cause
problems on the Mac if the new header were included with
#import
, but would break builds on other platforms
where #include
is used. Being consistent by using
#include
on all platforms means that compilation is
more likely to succeed everywhere or fail everywhere, and avoids
the frustration of files working only on some platforms.
While it may seem tempting to include individual system headers from a
framework such as Cocoa or Foundation, in fact it's less work on the
compiler if you include the top-level root framework. The root
framework is generally pre-compiled and can be loaded much more
quickly. In addition, remember to use #import
rather than
#include
for Objective-C frameworks.
autorelease
them on
the same line as you create them rather than a separate
release
later in the same method.
While ever so slightly slower, this prevents someone from accidentally
removing the release
or inserting a return
before it and introducing a memory leak. E.g.:
autorelease
then
retain
pattern.
When assigning a new object to a variable, one must first release the old object to avoid a memory leak. There are several "correct" ways to handle this. We've chosen the "autorelease then retain" approach because it's less prone to error. Be aware in tight loops it can fill up the autorelease pool, and may be slightly less efficient, but we feel the tradeoffs are acceptable.
init
and dealloc
method execution, so code in
those methods should avoid invoking accessors.
Subclasses have not yet been initialized or have already deallocated
when init
and dealloc
methods execute, making
accessor methods potentially unreliable. Whenever practical, directly
assign to and release ivars in those methods rather than rely on
accessors.
dealloc
should process instance variables in the same order
the @interface
declares them, so it is easier for a reviewer
to verify.
A code reviewer checking a new or revised dealloc
implementation needs to make sure that every retained instance
variable gets released.
To simplify reviewing dealloc
, order the code so that
the retained instance variables get released in the same order that
they are declared in the @interface
. If
dealloc
invokes other methods that release instance
variables, add comments describing what instance variables those
methods handle.
NSString
, should always copy
the string it accepts.
Never just retain
the string. This avoids the caller
changing it under you without your knowledge. Don't assume that
because you're accepting an NSString
that it's not
actually an NSMutableString
.
@throw
Objective-C exceptions, but you should be
prepared to catch them from third-party or OS calls.
We do compile with -fobjc-exceptions
(mainly so we get
@synchronized
), but we don't @throw
. Use of
@try
, @catch
, and @finally
are
allowed when required to properly use 3rd party code or libraries. If
you do use them please document exactly which methods you expect to
throw.
Do not use the NS_DURING
, NS_HANDLER
,
NS_ENDHANDLER
, NS_VALUERETURN
and
NS_VOIDRETURN
macros unless you are writing code that
needs to run on Mac OS X 10.2 or before.
Also be aware when writing Objective-C++ code that stack based objects are not cleaned up when you throw an Objective-C exception. Example:
will give you:
Note that the destructor for a never got called. This is a
major concern for stack based smartptrs such as
shared_ptr
and linked_ptr
, as well as any
STL objects that you may want to use. Therefore it pains us to say
that if you must use exceptions in your Objective-C++ code, use C++
exceptions whenever possible. You should never re-throw an Objective-C
exception, nor are stack based C++ objects (such as
std::string
, std::vector
etc.) allowed in
the body of any @try
, @catch
, or
@finally
blocks.
nil
checks for logic flow only.
Use nil
checks for logic flow of the application, not for
crash prevention. Sending a message to a nil
object is
handled by the Objective-C runtime. If the method has no return
result, you're good to go. However if there is one, there may be
differences based on runtime architecture, return size, and OS X
version (see Apple's
documentation for specifics).
Note that this is very different from checking C/C++ pointers against
NULL
, which the runtime does not handle and will cause
your application to crash. You still need to make sure you do not
dereference a NULL
pointer.
BOOL
.
Avoid comparing directly with YES
.
BOOL
is defined as a signed char in Objective-C which means
that it can have values other than YES
(1) and
NO
(0). Do not cast or convert general integral values
directly to BOOL
. Common mistakes include casting or
converting an array's size, a pointer value, or the result of a bitwise
logic operation to a BOOL
which, depending on the value of
the last byte of the integral result, could still result in a
NO
value. When converting a general integral value to a
BOOL
use ternery operators to return a YES
or
NO
value.
You can safely interchange and convert BOOL
,
_Bool
and bool
(see C++ Std 4.7.4, 4.12 and
C99 Std 6.3.1.2). You cannot safely interchange BOOL
and
Boolean
so treat Booleans
as a general
integral value as discussed above. Only use BOOL
in
Objective C method signatures.
Using logical operators (&&
, ||
and
!
) with BOOL
is also valid and will return
values that can be safely converted to BOOL
without the
need for a ternery operator.
Also, don't directly compare BOOL
variables directly
with YES
. Not only is it harder to read for those
well-versed in C, the first point above demonstrates that return
values may not always be what you expect.
@property
.
A property's associated instance variable's name must conform to the
leading _ requirement. The property's name should be the same as its
associated instance variable without the leading _. The optional space
between the @property
and the opening parenthesis
should be omitted, as seen in the examples.
A property's declaration must come immediately after the instance
variable block of a class interface. A property's definition (if
not using automatic synthesis) must come immediately after the
@implementation
block in a class definition. They are
indented at the same level as the @interface
or
@implementation
statements that they are enclosed in.
NSString properties should always be declared with the
copy
attribute.
This logically follows from the requirement that setters for
NSStrings always must use copy
instead of
retain
.
Be aware of the overhead of properties. By default, all synthesized
setters and getters are atomic. This gives each set and get calls a
substantial amount of synchronization overhead. Declare your
properties nonatomic
unless you require atomicity.
Dot notation is idiomatic style for Objective-C 2.0. It may be used
when doing simple operations to get and set a @property
of an object, but should not be used to invoke other object behavior.
Use of automatically synthesized instance variables is preferred. Code that must support earlier versions of the compiler toolchain (Xcode 4.3 or earlier or when compiling with GCC) or is using properties inherited from a protocol should prefer the @synthesize directive.
Automatically synthesized instance variables take the form of the property's name prefixed with an underscore and so typically conform to the required variable naming style. If your property name is unusual, or you are otherwise unable to use automatically synthesized instance variables, use of the @synthesize directive is preferred, with the instance variable name specified explicitly (as @synthesize does not add a leading underscore by default).
For projects that use Xcode 4.2 or later and will run only on 64-bit Mac OS X 10.7 and iOS 5.0 and later, ARC is preferred. Use manual reference counting when supporting earlier environments where zeroing weak pointers are not available.
Classes that require ARC should include a preprocessor directive to prevent compilation using manual reference counting.
Ownership qualifiers like __unsafe_unretained
and
__weak
should precede variable names. Specifying
__strong
for variables is not required since it is
the default. Properties, on the other hand, should always specify the
strong
keyword rather than relying on the compiler default.
Files that are compiled using ARC need to have preprocessor directives to prevent compilation without ARC. See the code snippet below for details.
Example of an implementation file enforcing ARC style. Note that
declaring instance variables in the @implementation is permitted when
using ARC.
For projects that use Xcode 4.4 or later with clang, the use of NSNumber literals is allowed. Note however that this will limit the portability of your code to other toolchains.
NSNumber literals are used just like Objective C string literals.
Boxing is used when necessary. Code using NSNumber literals can be
deployed on any iOS/MacOS system.
A class that implements the delegate pattern should:
delegate
and setDelegate:
.
@protocol
s for callback APIs.
@protocol
, using
@optional
if not all the methods are required.
(Exception: when using Objective-C 1.0, @optional
isn't
available, so use a category to define an "informal protocol".)
Our style guide used to have a rule saying that instance variables should be named with a trailing underscore, similar to the naming of member variables in C++. This was changed to leading underscores to be consistent with the broader Objective-C community, to better follow Apple's official guidelines, and to allow for use of new compiler features like automatic instance variable synthesis. New projects are strongly encouraged to use leading underscores. Existing projects may continue to use trailing underscores in new code to maintain consistency with the rest of their codebase.
Revision 2.52
Mike Pinkerton