mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
Add section on properties from dmaclach, remove some tabs.
This commit is contained in:
parent
48fcffea4c
commit
a7dd19342d
452
objcguide.xml
452
objcguide.xml
@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
|
|
||||||
<div align="right">
|
<div align="right">
|
||||||
<address>
|
<address>
|
||||||
Mike Pinkerton<br/>
|
Mike Pinkerton<br/>
|
||||||
Greg Miller <br/>
|
Greg Miller <br/>
|
||||||
Dave MacLachlan
|
Dave MacLachlan
|
||||||
</address>
|
</address>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<OVERVIEW>
|
<OVERVIEW>
|
||||||
|
|
||||||
<CATEGORY title="Important Note">
|
<CATEGORY title="Important Note">
|
||||||
@ -34,31 +34,40 @@
|
|||||||
|
|
||||||
<CATEGORY title="Background">
|
<CATEGORY title="Background">
|
||||||
|
|
||||||
<p>Objective-C is a very dynamic, object-oriented extension of C. It's
|
<p>
|
||||||
designed to be easy to use and read, while enabling sophisticated
|
Objective-C is a very dynamic, object-oriented extension of C. It's
|
||||||
object-oriented design. It is the primary development language for new
|
designed to be easy to use and read, while enabling sophisticated
|
||||||
applications on Mac OS X and the iPhone.</p>
|
object-oriented design. It is the primary development language for new
|
||||||
|
applications on Mac OS X and the iPhone.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>Cocoa is one of the main application frameworks on Mac OS X. It is a
|
<p>
|
||||||
collection of Objective-C classes that provide for rapid development of
|
Cocoa is one of the main application frameworks on Mac OS X. It is a
|
||||||
full-featured Mac OS X applications.</p>
|
collection of Objective-C classes that provide for rapid development of
|
||||||
|
full-featured Mac OS X applications.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>Apple has already written a very good, and widely accepted, coding guide
|
<p>
|
||||||
for Objective-C. Google has also written a similar guide for C++. This
|
Apple has already written a very good, and widely accepted, coding guide
|
||||||
Objective-C guide aims to be a very natural combination of Apple's and
|
for Objective-C. Google has also written a similar guide for C++. This
|
||||||
Google's general recommendations. So, before reading this guide, please make
|
Objective-C guide aims to be a very natural combination of Apple's and
|
||||||
sure you've read:
|
Google's general recommendations. So, before reading this guide, please make
|
||||||
<ul>
|
sure you've read:
|
||||||
<li><a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CodingGuidelines/index.html">Apple's
|
<ul>
|
||||||
Cocoa Coding Guidelines</a></li>
|
<li>
|
||||||
<li>
|
<a href="http://developer.apple.com/documentation/Cocoa/Conceptual/CodingGuidelines/index.html">
|
||||||
|
Apple's Cocoa Coding Guidelines
|
||||||
<div>
|
</a>
|
||||||
<a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml">Google's
|
</li>
|
||||||
Open Source C++ Style Guide</a>
|
<li>
|
||||||
</div>
|
|
||||||
</li>
|
<div>
|
||||||
</ul>
|
<a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml">
|
||||||
|
Google's Open Source C++ Style Guide
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
@ -80,8 +89,11 @@
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
Google has already released open-source code that conforms to these
|
Google has already released open-source code that conforms to these
|
||||||
guidelines as part of the <a href="http://code.google.com/p/google-toolbox-for-mac/">Google
|
guidelines as part of the
|
||||||
Toolbox for Mac project</a> (abbreviated GTM throughout this document).
|
<a href="http://code.google.com/p/google-toolbox-for-mac/">
|
||||||
|
Google Toolbox for Mac project
|
||||||
|
</a>
|
||||||
|
(abbreviated GTM throughout this document).
|
||||||
Code meant to be shared across different projects is a good candidate to
|
Code meant to be shared across different projects is a good candidate to
|
||||||
be included in this repository.
|
be included in this repository.
|
||||||
</p>
|
</p>
|
||||||
@ -91,124 +103,126 @@
|
|||||||
<p>
|
<p>
|
||||||
Note that this guide is not an Objective-C tutorial. We assume that the
|
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
|
reader is familiar with the language. If you are new to Objective-C or
|
||||||
need a refresher, please read <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/index.html">The
|
need a refresher, please read
|
||||||
Objective-C Programming Language</a>.
|
<a href="http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/index.html">
|
||||||
|
The Objective-C Programming Language
|
||||||
|
</a>.
|
||||||
</p>
|
</p>
|
||||||
</CATEGORY>
|
</CATEGORY>
|
||||||
</OVERVIEW>
|
</OVERVIEW>
|
||||||
|
|
||||||
<CATEGORY title="Example">
|
<CATEGORY title="Example">
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
They say an example is worth a thousand words so let's start off with an
|
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.
|
example that should give you a feel for the style, spacing, naming, etc.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
An example header file, demonstrating the correct commenting and spacing
|
An example header file, demonstrating the correct commenting and spacing
|
||||||
for an <code>@interface</code> declaration
|
for an <code>@interface</code> declaration
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<CODE_SNIPPET>
|
||||||
// GTMFoo.h
|
// GTMFoo.h
|
||||||
// FooProject
|
// FooProject
|
||||||
//
|
//
|
||||||
// Created by Greg Miller on 6/13/08.
|
// Created by Greg Miller on 6/13/08.
|
||||||
// Copyright 2008 Google, Inc. All rights reserved.
|
// Copyright 2008 Google, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
// A sample class demonstrating good Objective-C style. All interfaces,
|
// A sample class demonstrating good Objective-C style. All interfaces,
|
||||||
// categories, and protocols (read: all top-level declarations in a header)
|
// categories, and protocols (read: all top-level declarations in a header)
|
||||||
// MUST be commented. Comments must also be adjacent to the object they're
|
// MUST be commented. Comments must also be adjacent to the object they're
|
||||||
// documenting.
|
// documenting.
|
||||||
//
|
//
|
||||||
// (no blank line between this comment and the interface)
|
// (no blank line between this comment and the interface)
|
||||||
@interface GTMFoo : NSObject {
|
@interface GTMFoo : NSObject {
|
||||||
@private
|
@private
|
||||||
NSString *foo_;
|
NSString *foo_;
|
||||||
NSString *bar_;
|
NSString *bar_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an autoreleased instance of GMFoo. See -initWithString: for details
|
// Returns an autoreleased instance of GMFoo. See -initWithString: for details
|
||||||
// about the argument.
|
// about the argument.
|
||||||
+ (id)fooWithString:(NSString *)string;
|
+ (id)fooWithString:(NSString *)string;
|
||||||
|
|
||||||
// Designated initializer. |string| will be copied and assigned to |foo_|.
|
// Designated initializer. |string| will be copied and assigned to |foo_|.
|
||||||
- (id)initWithString:(NSString *)string;
|
- (id)initWithString:(NSString *)string;
|
||||||
|
|
||||||
// Gets and sets the string for |foo_|.
|
// Gets and sets the string for |foo_|.
|
||||||
- (NSString *)foo;
|
- (NSString *)foo;
|
||||||
- (void)setFoo:(NSString *)newFoo;
|
- (void)setFoo:(NSString *)newFoo;
|
||||||
|
|
||||||
// Does some work on |blah| and returns YES if the work was completed
|
// Does some work on |blah| and returns YES if the work was completed
|
||||||
// successfuly, and NO otherwise.
|
// successfuly, and NO otherwise.
|
||||||
- (BOOL)doWorkWithString:(NSString *)blah;
|
- (BOOL)doWorkWithString:(NSString *)blah;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
</pre>
|
</CODE_SNIPPET>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
An example source file, demonstating the correct commenting and spacing
|
An example source file, demonstating the correct commenting and spacing
|
||||||
for the <code>@implementation</code> of an interface. It also includes the
|
for the <code>@implementation</code> of an interface. It also includes the
|
||||||
reference implementations for important methods like getters and setters,
|
reference implementations for important methods like getters and setters,
|
||||||
<code>init</code>, and <code>dealloc</code>.
|
<code>init</code>, and <code>dealloc</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<CODE_SNIPPET>
|
||||||
//
|
//
|
||||||
// GTMFoo.m
|
// GTMFoo.m
|
||||||
// FooProject
|
// FooProject
|
||||||
//
|
//
|
||||||
// Created by Greg Miller on 6/13/08.
|
// Created by Greg Miller on 6/13/08.
|
||||||
// Copyright 2008 Google, Inc. All rights reserved.
|
// Copyright 2008 Google, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "GTMFoo.h"
|
#import "GTMFoo.h"
|
||||||
|
|
||||||
|
|
||||||
@implementation GTMFoo
|
@implementation GTMFoo
|
||||||
|
|
||||||
+ (id)fooWithString:(NSString *)string {
|
+ (id)fooWithString:(NSString *)string {
|
||||||
return [[[self alloc] initWithString:string] autorelease];
|
return [[[self alloc] initWithString:string] autorelease];
|
||||||
}
|
|
||||||
|
|
||||||
// Must always override super's designated initializer.
|
|
||||||
- (id)init {
|
|
||||||
return [self initWithString:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)initWithString:(NSString *)string {
|
|
||||||
if ((self = [super init])) {
|
|
||||||
foo_ = [string copy];
|
|
||||||
bar_ = [[NSString alloc] initWithFormat:@"hi %d", 3];
|
|
||||||
}
|
}
|
||||||
return self;
|
|
||||||
}
|
// Must always override super's designated initializer.
|
||||||
|
- (id)init {
|
||||||
- (void)dealloc {
|
return [self initWithString:nil];
|
||||||
[foo_ release];
|
}
|
||||||
[bar_ release];
|
|
||||||
[super dealloc];
|
- (id)initWithString:(NSString *)string {
|
||||||
}
|
if ((self = [super init])) {
|
||||||
|
foo_ = [string copy];
|
||||||
- (NSString *)foo {
|
bar_ = [[NSString alloc] initWithFormat:@"hi %d", 3];
|
||||||
return foo_;
|
}
|
||||||
}
|
return self;
|
||||||
|
}
|
||||||
- (void)setFoo:(NSString *)newFoo {
|
|
||||||
[foo_ autorelease];
|
- (void)dealloc {
|
||||||
foo_ = [newFoo copy];
|
[foo_ release];
|
||||||
}
|
[bar_ release];
|
||||||
|
[super dealloc];
|
||||||
- (BOOL)doWorkWithString:(NSString *)blah {
|
}
|
||||||
// ...
|
|
||||||
return NO;
|
- (NSString *)foo {
|
||||||
}
|
return foo_;
|
||||||
|
}
|
||||||
@end
|
|
||||||
</pre>
|
- (void)setFoo:(NSString *)newFoo {
|
||||||
|
[foo_ autorelease];
|
||||||
|
foo_ = [newFoo copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)doWorkWithString:(NSString *)blah {
|
||||||
|
// ...
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
</CODE_SNIPPET>
|
||||||
|
|
||||||
</CATEGORY>
|
</CATEGORY>
|
||||||
|
|
||||||
@ -828,11 +842,11 @@
|
|||||||
<BODY>
|
<BODY>
|
||||||
<p>
|
<p>
|
||||||
Unlike C++, Objective-C doesn't have a way to differentiate between
|
Unlike C++, Objective-C doesn't have a way to differentiate between
|
||||||
public and private methods — everything is public. As a result, avoid
|
public and private methods — everything is public. As a result,
|
||||||
placing methods in the public API unless they are actually expected to
|
avoid placing methods in the public API unless they are actually
|
||||||
be used by a consumer of the class. This helps reduce the likelihood
|
expected to be used by a consumer of the class. This helps reduce the
|
||||||
they'll be called when you're not expecting it. This includes methods
|
likelihood they'll be called when you're not expecting it. This includes
|
||||||
that are being overridden from the parent class. For internal
|
methods that are being overridden from the parent class. For internal
|
||||||
implementation methods, use a category defined in the implementation
|
implementation methods, use a category defined in the implementation
|
||||||
file as opposed to adding them to the public header.
|
file as opposed to adding them to the public header.
|
||||||
</p>
|
</p>
|
||||||
@ -1123,9 +1137,177 @@
|
|||||||
</CODE_SNIPPET>
|
</CODE_SNIPPET>
|
||||||
</BODY>
|
</BODY>
|
||||||
</STYLEPOINT>
|
</STYLEPOINT>
|
||||||
|
|
||||||
|
<STYLEPOINT title="Properties">
|
||||||
|
<SUMMARY>
|
||||||
|
Properties in general are allowed with the following caveat: properties
|
||||||
|
are an Objective-C 2.0 feature which will limit your code to running
|
||||||
|
on the iPhone and MacOS X 10.5 (Leopard) and higher. Dot notation to
|
||||||
|
access properties is not allowed.
|
||||||
|
</SUMMARY>
|
||||||
|
<BODY>
|
||||||
|
<SUBSECTION title="Naming">
|
||||||
|
<p>
|
||||||
|
A property's associated instance variable's name must conform to the
|
||||||
|
trailing _ requirement. The property's name should be the same as its
|
||||||
|
associated instance variable without the trailing _.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Use the @synthesize directive to rename the property correctly.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<CODE_SNIPPET>
|
||||||
|
@interface MyClass : NSObject {
|
||||||
|
@private
|
||||||
|
NSString *name_;
|
||||||
|
}
|
||||||
|
@property(copy, nonatomic) NSString *name;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MyClass
|
||||||
|
@synthesize name = name_;
|
||||||
|
@end
|
||||||
|
</CODE_SNIPPET>
|
||||||
|
</SUBSECTION>
|
||||||
|
<SUBSECTION title="Location">
|
||||||
|
<p>
|
||||||
|
A property's declaration must come immediately after the instance
|
||||||
|
variable block of a class interface. A property's definition must
|
||||||
|
come immediately after the <code>@implementation</code> block in a
|
||||||
|
class definition. They are indented at the same level as the
|
||||||
|
<code>@interface</code> or <code>@implementation</code> statements
|
||||||
|
that they are enclosed in.
|
||||||
|
</p>
|
||||||
|
<CODE_SNIPPET>
|
||||||
|
@interface MyClass : NSObject {
|
||||||
|
@private
|
||||||
|
NSString *name_;
|
||||||
|
}
|
||||||
|
@property(copy, nonatomic) NSString *name;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MyClass
|
||||||
|
@synthesize name = name_;
|
||||||
|
- (id)init {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
</CODE_SNIPPET>
|
||||||
|
</SUBSECTION>
|
||||||
|
<SUBSECTION title="Use Copy Attribute For Strings">
|
||||||
|
<p>
|
||||||
|
NSString properties should always be declared with the
|
||||||
|
<code>copy</code> attribute.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This logically follows from the requirement that setters for
|
||||||
|
NSStrings always must use <code>copy</code> instead of
|
||||||
|
<code>retain</code>.
|
||||||
|
</p>
|
||||||
|
</SUBSECTION>
|
||||||
|
<SUBSECTION title="Never synthesize CFType properties">
|
||||||
|
<p>
|
||||||
|
CFTypes should always have the <code>@dynamic</code> implementation
|
||||||
|
directive.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Since CFTypes can't have the <code>retain</code> property
|
||||||
|
attribute, the developer must handle retaining and releasing the
|
||||||
|
value themselves. In the rare case that you do actually want
|
||||||
|
assignment it is better to make that completely clear by actually
|
||||||
|
implementing the setter and getter and commenting why that is the
|
||||||
|
case.
|
||||||
|
</p>
|
||||||
|
</SUBSECTION>
|
||||||
|
<SUBSECTION title="List out all implementation directives">
|
||||||
|
<p>
|
||||||
|
Use implementation directives for all properties even if they are
|
||||||
|
<code>@dynamic</code> by default.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Even though <code>@dynamic</code> is default, explicitly list it out
|
||||||
|
with all of the other property implementation directives making it
|
||||||
|
clear how every property in a class is handled at a single glance.
|
||||||
|
</p>
|
||||||
|
<BAD_CODE_SNIPPET>
|
||||||
|
@interface MyClass : NSObject
|
||||||
|
@property(readonly) NSString *name;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MyClass
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
- (NSString*)name {
|
||||||
|
return @"foo";
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
</BAD_CODE_SNIPPET>
|
||||||
|
<CODE_SNIPPET>
|
||||||
|
@interface MyClass : NSObject
|
||||||
|
@property(readonly) NSString *name;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MyClass
|
||||||
|
@dynamic name;
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
- (NSString*)name {
|
||||||
|
return @"foo";
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
</CODE_SNIPPET>
|
||||||
|
</SUBSECTION>
|
||||||
|
<SUBSECTION title="Atomicity">
|
||||||
|
<p>
|
||||||
|
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 <code>nonatomic</code> unless you require atomicity.
|
||||||
|
</p>
|
||||||
|
</SUBSECTION>
|
||||||
|
<SUBSECTION title="Dot notation">
|
||||||
|
<p>
|
||||||
|
We do not allow the use of dot notation to access properties for
|
||||||
|
the following reasons:
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
Dot notation is purely syntactic sugar for standard method calls,
|
||||||
|
whose readability gains are debatable. It just gives you another
|
||||||
|
way to make method calls.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
It obscures the type that you are dereferencing. When one sees:
|
||||||
|
<code>[foo setBar:1]</code> it is immediately clear that you are
|
||||||
|
working with an Objective-C object. When one sees
|
||||||
|
<code>foo.bar = 1</code> it is not clear if foo is an object, or
|
||||||
|
a struct/union/C++ class.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
It allows you to do method calls that look like getters.
|
||||||
|
<BAD_CODE_SNIPPET>
|
||||||
|
NSString *upperCase = @"foo".uppercaseString;
|
||||||
|
</BAD_CODE_SNIPPET>
|
||||||
|
which is not only confusing, but difficult to spot in a code review.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
It hides method calls.
|
||||||
|
<BAD_CODE_SNIPPET>
|
||||||
|
bar.value += 10;
|
||||||
|
</BAD_CODE_SNIPPET>
|
||||||
|
is actually two separate method calls (one to set and one to get)
|
||||||
|
and if your properties are not simple you may find a lot of work
|
||||||
|
being done in a hidden manner.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</SUBSECTION>
|
||||||
|
</BODY>
|
||||||
|
</STYLEPOINT>
|
||||||
</CATEGORY>
|
</CATEGORY>
|
||||||
|
|
||||||
|
|
||||||
<CATEGORY title="Cocoa Patterns">
|
<CATEGORY title="Cocoa Patterns">
|
||||||
|
|
||||||
<STYLEPOINT title="Delegate Pattern">
|
<STYLEPOINT title="Delegate Pattern">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user