diff --git a/objcguide.md b/objcguide.md new file mode 100644 index 000000000..fd4bb97ef --- /dev/null +++ b/objcguide.md @@ -0,0 +1,1606 @@ +# Google Objective-C Style Guide + +> Objective-C is a 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 applications on OS X and on iOS. +> +> Apple has already written a very good, and widely accepted, [Cocoa Coding +> Guidelines](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html) +> for Objective-C. Please read it in addition to this guide. +> +> +> The purpose of this document is to describe the Objective-C (and +> Objective-C++) coding guidelines and practices that should be used for iOS and +> OS X code. 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. +> +> 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 [Programming with +> Objective-C](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html). + + +## Example + +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, and so on. + +Here is an example header file, demonstrating the correct commenting and spacing +for an `@interface` declaration. + +Doxygen-style comments are encouraged for interfaces as they are parsed by Xcode +to display formatted documentation. There is a wide variety of Doxygen commands; +use them consistently within a project. + +```objectivec +// GOOD: + +#import + +@class Bar; + +/** + * A sample class demonstrating good Objective-C style. All interfaces, + * categories, and protocols (read: all non-trivial top-level declarations + * in a header) MUST be commented. Comments must also be adjacent to the + * object they're documenting. + */ +@interface Foo : NSObject + +/** The retained Bar. */ +@property(nonatomic) Bar *bar; + +/** The current drawing attributes. */ +@property(nonatomic, copy) NSDictionary *attributes; + +/** + * Convenience creation method. + * See -initWithBar: for details about @c bar. + * + * @param bar The string for fooing. + * @return An instance of Foo. + */ ++ (instancetype)fooWithBar:(Bar *)bar; + +/** + * Designated initializer. + * + * @param bar A string that represents a thing that does a thing. + */ +- (instancetype)initWithBar:(Bar *)bar; + +/** + * Does some work with @c blah. + * + * @param blah + * @return YES if the work was completed; NO otherwise. + */ +- (BOOL)doWorkWithBlah:(NSString *)blah; + +@end +``` + +An example source file, demonstrating the correct commenting and spacing for the +`@implementation` of an interface. + +```objectivec +// GOOD: + +#import "Shared/Util/Foo.h" + +@implementation Foo { + // The string used for displaying "hi". + NSString *_string; +} + ++ (instancetype)fooWithBar:(Bar *)bar { + return [[self alloc] initWithBar:bar]; +} + +- (instancetype)init { + // Classes with a custom designated initializer should always override + // the superclass's designated initializer. + return [self initWithBar:nil]; +} + +- (instancetype)initWithBar:(Bar *)bar { + self = [super init]; + if (self) { + _bar = [bar copy]; + _string = [[NSString alloc] initWithFormat:@"hi %d", 3]; + _attributes = @{ + @"color" : [UIColor blueColor], + @"hidden" : @NO + }; + } + return self; +} + +- (BOOL)doWorkWithBlah:(NSString *)blah { + // Work should be done here. + return NO; +} + +@end +``` + +## Spacing and Formatting + +### Spaces vs. Tabs + +Use only spaces, and indent 2 spaces at a time. 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, and to trim +trailing spaces on lines. + +### Line Length + +The maximum line length for Objective-C files is 100 columns. + +You can make violations easier to spot by enabling *Preferences > Text Editing > +Page guide at column: 100* in Xcode. + +### Method Declarations and Definitions + +One space should be used between the `-` or `+` and the return type, and no +spacing in the parameter list except between parameters. + +Methods should look like this: + +```objectivec +// GOOD: + +- (void)doSomethingWithString:(NSString *)theString { + ... +} +``` + +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. + +```objectivec +// GOOD: + +- (void)doSomethingWithFoo:(GTMFoo *)theFoo + rect:(NSRect)theRect + interval:(float)theInterval { + ... +} +``` + +When the second or later parameter name is longer than the first, indent the +second and later lines by at least four spaces, maintaining colon alignment: + +```objectivec +// GOOD: + +- (void)short:(GTMFoo *)theFoo + longKeyword:(NSRect)theRect + evenLongerKeyword:(float)theInterval + error:(NSError **)theError { + ... +} +``` + +### Conditionals + +Include a space after `if`, `while`, `for`, and `switch`, and around comparison +operators. + +```objectivec +// GOOD: + +for (int i = 0; i < 5; ++i) { +} + +while (test) {}; +``` + +Braces may be omitted when a loop body or conditional statement fits on a single +line. + +```objectivec +// GOOD: + +if (hasSillyName) LaughOutLoud(); + +for (int i = 0; i < 10; i++) { + BlowTheHorn(); +} +``` + +```objectivec +// AVOID: + +if (hasSillyName) + LaughOutLoud(); // AVOID. + +for (int i = 0; i < 10; i++) + BlowTheHorn(); // AVOID. +``` + +If an `if` clause has an `else` clause, both clauses should use braces. + +```objectivec +// GOOD: + +if (hasBaz) { + foo(); +} else { + bar(); +} +``` + +```objectivec +// AVOID: + +if (hasBaz) foo(); +else bar(); // AVOID. + +if (hasBaz) { + foo(); +} else bar(); // AVOID. +``` + +Intentional fall-through to the next case should be documented with a comment +unless the case has no intervening code before the next case. + +```objectivec +// GOOD: + +switch (i) { + case 1: + ... + break; + case 2: + j++; + // Falls through. + case 3: { + int k; + ... + break; + } + case 4: + case 5: + case 6: break; +} +``` + +### Expressions + +Use a space around binary operators and assignments. Omit a space for a unary +operator. Do not add spaces inside parentheses. + +```objectivec +// GOOD: + +x = 0; +v = w * x + y / z; +v = -y * (x + z); +``` + +Factors in an expression may omit spaces. + +```objectivec +// GOOD: + +v = w*x + y/z; +``` + +### Method Invocations + +Method invocations should be formatted much like method declarations. + +When there's a choice of formatting styles, follow the convention already used +in a given source file. Invocations should have all arguments on one line: + +```objectivec +// GOOD: + +[myObject doFooWith:arg1 name:arg2 error:arg3]; +``` + +or have one argument per line, with colons aligned: + +```objectivec +// GOOD: + +[myObject doFooWith:arg1 + name:arg2 + error:arg3]; +``` + +Don't use any of these styles: + +```objectivec +// AVOID: + +[myObject doFooWith:arg1 name:arg2 // some lines with >1 arg + error:arg3]; + +[myObject doFooWith:arg1 + name:arg2 error:arg3]; + +[myObject doFooWith:arg1 + name:arg2 // aligning keywords instead of colons + error:arg3]; +``` + +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: + +```objectivec +// GOOD: + +[myObj short:arg1 + longKeyword:arg2 + evenLongerKeyword:arg3 + error:arg4]; +``` + +Invocations containing multiple inlined blocks may have their parameter names +left-aligned at a four space indent. + +### Function Calls + +Function calls should include as many parameters as fit on each line, except +where shorter lines are needed for clarity or documentation of the parameters. + +Continuation lines for function parameters may be indented to align with the +opening parenthesis, or may have a four-space indent. + +```objectivec +// GOOD: + +CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, objects, numberOfObjects, + &kCFTypeArrayCallBacks); + +NSString *string = NSLocalizedStringWithDefaultValue(@"FEET", @"DistanceTable", + resourceBundle, @"%@ feet", @"Distance for multiple feet"); + +UpdateTally(scores[x] * y + bases[x], // Score heuristic. + x, y, z); + +TransformImage(image, + x1, x2, x3, + y1, y2, y3, + z1, z2, z3); +``` + +Use local variables with descriptive names to shorten function calls and reduce +nesting of calls. + +```objectivec +// GOOD: + +double scoreHeuristic = scores[x] * y + bases[x]; +UpdateTally(scoreHeuristic, x, y, z); +``` + +### Exceptions + +Format exceptions with `@catch` and `@finally` labels on the same line as the +preceding `}`. Add a space between the `@` label and the opening brace (`{`), as +well as between the `@catch` and the caught object declaration. If you must use +Objective-C exceptions, format them as follows. However, see Avoid Throwing +Exceptions for reasons why you should not be using exceptions. + +```objectivec +// GOOD: + +@try { + foo(); +} @catch (NSException *ex) { + bar(ex); +} @finally { + baz(); +} +``` + +### Function Length + +Prefer small and focused functions. + +Long functions and methods are occasionally appropriate, so no hard limit is +placed on function length. If a function exceeds about 40 lines, think about +whether it can be broken up without harming the structure of the program. + +Even if your long function works perfectly now, someone modifying it in a few +months may add new behavior. This could result in bugs that are hard to find. +Keeping your functions short and simple makes it easier for other people to read +and modify your code. + +When updating legacy code, consider also breaking long functions into smaller +and more manageable pieces. + +### Vertical Whitespace + +Use vertical whitespace sparingly. + +To allow more code to be easily viewed on a screen, avoid putting blank lines +just inside the braces of functions. + +Limit blank lines to one or two between functions and between logical groups of +code. + +## Naming + +Names should be as descriptive as possible, within reason. Follow standard +[Objective-C naming +rules](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html). + +Avoid non-standard abbreviations. 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: + +```objectivec +// GOOD: + +// Good names. +int numberOfErrors = 0; +int completedConnectionsCount = 0; +tickets = [[NSMutableArray alloc] init]; +userInfo = [someObject object]; +port = [network port]; +NSDate *gAppLaunchDate; +``` + +```objectivec +// AVOID: + +// Names to avoid. +int w; +int nerr; +int nCompConns; +tix = [[NSMutableArray alloc] init]; +obj = [someObject object]; +p = [network port]; +``` + +Any class, category, method, function, or variable name should use all capitals +for acronyms and +[initialisms](https://en.wikipedia.org/wiki/Initialism) +within the name. This follows Apple's standard of using all capitals within a +name for acronyms such as URL, ID, TIFF, and EXIF. + +Names of C functions and typedefs should be capitalized and use camel case as +appropriate for the surrounding code. + +### File Names + +File names should reflect the name of the class implementation that they +contain—including case. + +Follow the convention that your project uses. +File extensions should be as follows: + +Extension | Type +--------- | --------------------------------- +.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 + +Files containing code that may be shared across projects or used in a large +project should have a clearly unique name, typically including the project or +class prefix. + +File names for categories should include the name of the class being extended, +like GTMNSString+Utils.h or NSTextView+GTMAutocomplete.h + +### Class Names + +Class names (along with category and protocol names) should start as uppercase +and use mixed case to delimit words. + +When designing code to be shared across multiple applications, prefixes are +acceptable and recommended (e.g. GTMSendMessage). Prefixes are also recommended +for classes of large applications that depend on external libraries. + +### Category Names + +Category names should start with a 3 character prefix identifying the category +as part of a project or open for general use. + +The category name should incorporate the name of the class it's extending. For +example, if we want to create a category on `NSString` for parsing, we would put +the category in a file named `NSString+GTMParsing.h`, and the category itself +would be named `GTMNSStringParsingAdditions`. The file name and the category may +not match, as 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's global namespace. + +There should be a single space between the class name and the opening +parenthesis of the category. + +```objectivec +// GOOD: + +// Using a category to extend a Foundation class. +@interface NSString (GTMNSStringParsingAdditions) +- (NSString *)gtm_parsedString; +@end +``` + +### Objective-C Method Names + +Method and parameter names typically start as lowercase and then use mixed case. + +Proper capitalization should be respected, including at the beginning of names. + +```objectivec +// GOOD: + ++ (NSURL *)URLWithString; +``` + +The method name should read like a sentence if possible, meaning you should +choose parameter names that flow with the method name. 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 implementation comments unnecessary. + +Use prepositions and conjunctions like "with", "from", and "to" in the second +and later parameter names only where necessary to clarify the meaning or +behavior of the method. + +```objectivec +// GOOD: + +- (void)addTarget:(id)target action:(SEL)action; // GOOD; no conjunction needed +- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view; // GOOD; conjunction clarifies parameter +- (void)replaceCharactersInRange:(NSRange)aRange + withAttributedString:(NSAttributedString *)attributedString; // GOOD. +``` + +A method that returns an object should have a name beginning with a noun +identifying the object returned: + +```objectivec +// GOOD: + +- (Sandwich *)sandwich; // GOOD. +``` + +```objectivec +// AVOID: + +- (Sandwich *)makeSandwich; // AVOID. +``` + +An accessor method should be named the same as the object it's getting, but it +should not be prefixed with the word `get`. For example: + +```objectivec +// GOOD: + +- (id)delegate; // GOOD. +``` + +```objectivec +// AVOID: + +- (id)getDelegate; // AVOID. +``` + +Accessors that return the value of boolean adjectives have method names +beginning with `is`, but property names for those methods omit the `is`. + +Dot notation is used only with property names, not with method names. + +```objectivec +// GOOD: + +@property(nonatomic, getter=isGlorious) BOOL glorious; +- (BOOL)isGlorious; + +BOOL isGood = object.glorious; // GOOD. +BOOL isGood = [object isGlorious]; // GOOD. +``` + +```objectivec +// AVOID: + +BOOL isGood = object.isGlorious; // AVOID. +``` + +```objectivec +// GOOD: + +NSArray *frogs = [NSArray arrayWithObject:frog]; +NSEnumerator *enumerator = [frogs reverseObjectEnumerator]; // GOOD. +``` + +```objectivec +// AVOID: + +NSEnumerator *enumerator = frogs.reverseObjectEnumerator; // AVOID. +``` + +See [Apple's Guide to Naming +Methods](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282-BCIGIJJF) +for more details on Objective-C naming. + +These guidelines are for Objective-C methods only. C++ method names continue to +follow the rules set in the C++ style guide. + +### Function Names + +Regular functions have mixed case. + +Ordinarily, functions should start with a capital letter and have a capital +letter for each new word (a.k.a. "[Camel +Case](https://en.wikipedia.org/wiki/Camel_case)" or "Pascal case"). + +```objectivec +// GOOD: + +static void AddTableEntry(NSString *tableEntry); +static BOOL DeleteFile(char *filename); +``` + +Because Objective-C does not provide namespacing, non-static functions should +have a prefix that minimizes the chance of a name collision. + +```objectivec +// GOOD: + +extern NSTimeZone *GTMGetDefaultTimeZone(); +extern NSString *GTMGetURLScheme(NSURL *URL); +``` + +### Variable Names + +Variable names typically start with a lowercase and use mixed case to delimit +words. + +Instance variables have leading underscores. File scope or global variables have +a prefix `g`. For example: `myLocalVariable`, `_myInstanceVariable`, +`gMyGlobalVariable`. + +#### Common Variable Names + +Readers should be able to infer the variable type from the name, but do not use +Hungarian notation for syntactic attributes, such as the static type of a +variable (int or pointer). + +File scope or global variables (as opposed to constants) declared outside the +scope of a method or function should be rare, and should have the prefix g. + +```objectivec +// GOOD: + +static int gGlobalCounter; +``` + +#### Instance Variables + +Instance variable names are mixed case and should be prefixed with an +underscore, like `_usernameTextField`. + +NOTE: Google's previous convention for Objective-C ivars was a trailing +underscore. Existing projects may opt to continue using trailing underscores in +new code in order to maintain consistency within the project codebase. +Consistency of prefix or suffix underscores should be maintained within each +class. + +#### Constants + +Constant symbols (const global and static variables and constants created +with #define) should use mixed case to delimit words. + +Constants should have an appropriate prefix. + +```objectivec +// GOOD: + +extern NSString *const GTLServiceErrorDomain; + +typedef NS_ENUM(NSInteger, GTLServiceError) { + GTLServiceErrorQueryResultMissing = -3000, + GTLServiceErrorWaitTimedOut = -3001, +}; +``` + +Because Objective-C does not provide namespacing, constants with external +linkage should have a prefix that minimizes the chance of a name collision, +typically like `ClassNameConstantName` or `ClassNameEnumName`. + +For interoperability with Swift code, enumerated values should have names that +extend the typedef name: + +```objectivec +// GOOD: + +typedef NS_ENUM(NSInteger, DisplayTinge) { + DisplayTingeGreen = 1, + DisplayTingeBlue = 2, +}; +``` + +Constants may use a lowercase k prefix when appropriate: + +```objectivec +// GOOD: + +static const int kFileCount = 12; +static NSString *const kUserKey = @"kUserKey"; +``` + +## Types and Declarations + +### Local Variables + +Declare variables in the narrowest practical scopes, and close to their use. +Initialize variables in their declarations. + +```objectivec +// GOOD: + +CLLocation *location = [self lastKnownLocation]; +for (int meters = 1; meters < 10; meters++) { + reportFrogsWithinRadius(location, meters); +} +``` + +Occasionally, efficiency will make it more appropriate to declare a variable +outside the scope of its use. This example declares meters separate from +initialization, and needlessly sends the lastKnownLocation message each time +through the loop: + +```objectivec +// AVOID: + +int meters; // AVOID. +for (meters = 1; meters < 10; meters++) { + CLLocation *location = [self lastKnownLocation]; // AVOID. + reportFrogsWithinRadius(location, meters); +} +``` + +Under Automatic Reference Counting, pointers to Objective-C objects are by +default initialized to `nil`, so explicit initialization to `nil` is not +required. + +### Unsigned Integers + +Avoid unsigned integers except when matching types used by system interfaces. + +Subtle errors crop up when doing math or counting down to zero using unsigned +integers. Rely only on signed integers in math expressions except when matching +NSUInteger in system interfaces. + +```objectivec +// GOOD: + +NSUInteger numberOfObjects = array.count; +for (NSInteger counter = numberOfObjects - 1; counter > 0; --counter) +``` + +```objectivec +// AVOID: + +for (NSUInteger counter = numberOfObjects - 1; counter > 0; --counter) // AVOID. +``` + +Unsigned integers may be used for flags and bitmasks, though often NS_OPTIONS or +NS_ENUM will be more appropriate. + +### Types with Inconsistent Sizes + +Due to sizes that differ in 32- and 64-bit builds, avoid types long, NSInteger, +NSUInteger, and CGFloat except when matching system interfaces. + +Types long, NSInteger, NSUInteger, and CGFloat vary in size between 32- and +64-bit builds. Use of these types is appropriate when handling values exposed by +system interfaces, but they should be avoided for most other computations. + +```objectivec +// GOOD: + +int32_t scalar1 = proto.intValue; + +int64_t scalar2 = proto.longValue; + +NSUInteger numberOfObjects = array.count; + +CGFloat offset = view.bounds.origin.x; +``` + +```objectivec +// AVOID: + +NSInteger scalar2 = proto.longValue; // AVOID. +``` + +File and buffer sizes often exceed 32-bit limits, so they should be declared +using `int64_t`, not with `long`, `NSInteger`, or `NSUInteger`. + +## Comments + +Comments are absolutely vital to keeping our code readable. The following rules +describe what you should comment and where. But remember: while comments are +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. + +Pay attention to punctuation, spelling, and grammar; it is easier to read +well-written comments than badly written ones. + +Comments should be as readable as narrative text, with proper capitalization and +punctuation. In many cases, complete sentences are more readable than sentence +fragments. Shorter comments, such as comments at the end of a line of code, can +sometimes be less formal, but use a consistent style. +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! + +### File Comments + +A file may optionally start with a description of its contents. +Every file may contain the following items, in order: + * License boilerplate if necessary. Choose the appropriate boilerplate for the license used by the project. + * A basic description of the contents of the file if necessary. + +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. + + +### Declaration Comments + +Every non-trivial interface, public and private, should have an accompanying +comment describing its purpose and how it fits into the larger picture. + +Comments should be used to document classes, properties, ivars, functions, +categories, protocol declarations, and enums. + +```objectivec +// GOOD: + +/** + * A delegate for NSApplication to handle notifications about app + * launch and shutdown. Owned by the main app controller. + */ +@interface MyAppDelegate : NSObject { + /** + * The background task in progress, if any. This is initialized + * to the value UIBackgroundTaskInvalid. + */ + UIBackgroundTaskIdentifier _backgroundTaskID; +} + +/** The factory that creates and manages fetchers for the app. */ +@property(nonatomic) GTMSessionFetcherService *fetcherService; + +@end +``` + +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 should have a comment explaining its function, +arguments, return value, thread or queue assumptions, and any side effects. +Documentation comments should be in the header for public methods, or +immediately preceding the method for non-trivial private methods. + +Use descriptive form ("Opens the file") rather than imperative form ("Open the +file") for method and function comments. The comment describes the function; it +does not tell the function what to do. + +Document the thread usage assumptions the class, properties, or methods make, 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. + +Any sentinel values for properties and ivars, such as `NULL` or `-1`, should be +documented in comments. + +Declaration comments explain how a method or function is used. Comments +explaining how a method or function is implemented should be with the +implementation rather than with the declaration. + +### Implementation Comments + +Provide comments explaining tricky, subtle, or complicated sections of code. + +```objectivec +// GOOD: + +// Set the property to nil before invoking the completion handler to +// avoid the risk of reentrancy leading to the callback being +// invoked again. +CompletionHandler handler = self.completionHandler; +self.completionHandler = nil; +handler(); +``` + +When useful, also provide comments about implementation approaches that were +considered or abandoned. + +End-of-line comments should be separated from the code by at least 2 spaces. If +you have several comments on subsequent lines, it can often be more readable to +line them up. + +```objectivec +// GOOD: + +[self doSomethingWithALongName]; // Two spaces before the comment. +[self doSomethingShort]; // More spacing to align the comment. +``` + +### Disambiguating Symbols + +Where needed to avoid ambiguity, use backticks or vertical bars to quote +variable names and symbols in comments in preference to using quotation marks +or naming the symbols inline. + +In Doxygen-style comments, prefer demarcating symbols with a monospace text +command, such as `@c`. + +Demarcation helps provide clarity when a symbol is a common word that might make +the sentence read like it was poorly constructed. A common example is the symbol +`count`: + +```objectivec +// GOOD: + +// Sometimes `count` will be less than zero. +``` + +or when quoting something which already contains quotes + +```objectivec +// GOOD: + +// Remember to call `StringWithoutSpaces("foo bar baz")` +``` + +Backticks or vertical bars are not needed when a symbol is self-apparent. + +```objectivec +// GOOD: + +// This class serves as a delegate to GTMDepthCharge. +``` + +Doxygen formatting is also suitable for identifying symbols. + +```objectivec +// GOOD: + +/** @param maximum The highest value for @c count. */ +``` + +### Object Ownership + +For objects not managed by ARC, make the pointer ownership model as explicit as +possible when it falls outside the most common Objective-C usage idioms. + +#### Manual Reference Counting + +Instance variables for NSObject-derived objects are presumed to be retained; if +they are not retained, they should be either commented as weak or declared with +the `__weak` lifetime qualifier. + +An exception is in Mac software for instance variables labeled as `@IBOutlets`, +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 strong and weak +comments 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. + +Examples of strong and weak declarations: + +```objectivec +// GOOD: + +@interface MyDelegate : NSObject + +@property(nonatomic) NSString *doohickey; +@property(nonatomic, weak) NSString *parent; + +@end + + +@implementation MyDelegate { + IBOutlet NSButton *_okButton; // Normal NSControl; implicitly weak on Mac only + + AnObjcObject *_doohickey; // My doohickey + MyObjcParent * __weak _parent; // To send messages back (owns this instance) + + // non-NSObject pointers... + CWackyCPPClass *_wacky; // Strong, some cross-platform object + CFDictionaryRef *_dict; // Strong +} +@end +``` + +#### Automatic Reference Counting + +Object ownership and lifetime are explicit when using ARC, so no additional +comments are required for automatically retained objects. + +## C Language Features + +### Macros + +Avoid macros, especially where `const` variables, enums, XCode snippets, or C +functions may be used instead. + +Macros make the code you see different from the code the compiler sees. Modern C +renders traditional uses of macros for constants and utility functions +unnecessary. Macros should only be used when there is no other solution +available. + +Where a macro is needed, use a unique name to avoid the risk of a symbol +collision in the compilation unit. If practical, keep the scope limited by +`#undefining` the macro after its use. + +Macro names should use `SHOUTY_SNAKE_CASE`—all uppercase letters with +underscores between words. Function-like macros may use C function naming +practices. Do not define macros that appear to be C or Objective-C keywords. + +```objectivec +// GOOD: + +#define GTM_EXPERIMENTAL_BUILD ... // GOOD + +// Assert unless X > Y +#define GTM_ASSERT_GT(X, Y) ... // GOOD, macro style. + +// Assert unless X > Y +#define GTMAssertGreaterThan(X, Y) ... // GOOD, function style. +``` + +```objectivec +// AVOID: + +#define kIsExperimentalBuild ... // AVOID + +#define unless(X) if(!(X)) // AVOID +``` + +Avoid macros that expand to unbalanced C or Objective-C constructs. Avoid macros +that introduce scope, or may obscure the capturing of values in blocks. + +Avoid macros that generate class, property, or method definitions in +headers to be used as public API. These only make the code hard to +understand, and the language already has better ways of doing this. + +Avoid macros that generate method implementations, or that generate declarations +of variables that are later used outside of the macro. Macros shouldn't make +code hard to understand by hiding where and how a variable is declared. + +```objectivec +// AVOID: + +#define ARRAY_ADDER(CLASS) \ + -(void)add ## CLASS ## :(CLASS *)obj toArray:(NSMutableArray *)array + +ARRAY_ADDER(NSString) { + if (array.count > 5) { // AVOID -- where is 'array' defined? + ... + } +} +``` + +Examples of acceptable macro use include assertion and debug logging macros +that are conditionally compiled based on build settings—often, these are +not compiled into release builds. + +### Nonstandard Extensions + +Nonstandard extensions to C/Objective-C may not be used unless otherwise +specified. + +Compilers support various extensions that are not part of standard C. Examples +include compound statement expressions (e.g. `foo = ({ int x; Bar(&x); x }))` +and variable-length arrays. + +`__attribute__` is an approved exception, as it is used in Objective-C API +specifications. + +The binary form of the conditional operator, `A ?: B`, is an approved exception. + +## Cocoa and Objective-C Features + +### Identify Designated Initializer + +Clearly identify your designated initializer. + +It is important for those who might be subclassing your class that the +designated initializer be clearly identified. That way, they only need to +override a single initializer (of potentially several) to guarantee the +initializer of their subclass 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. Identify the designated initializer using comments or the +`NS_DESIGNATED_INITIALIZER` macro. If you use `NS_DESIGNATED_INITIALIZER`, mark +unsupported initializers with `NS_UNAVAILABLE`. + +### Override Designated Initializer + +When writing a subclass that requires an `init...` method, make sure you +override the designated initializer of the superclass. + +If you fail to override the designated initializer of the superclass, your +initializer may not be called in all cases, leading to subtle and very difficult +to find bugs. + +### Overridden NSObject Method Placement + +Put overridden methods of NSObject at the top of an `@implementation`. + +This commonly applies to (but is not limited to) the `init...`, `copyWithZone:`, +and `dealloc` methods. The `init...` methods should be grouped together, +followed by other typical `NSObject` methods such as `description`, `isEqual:`, +and `hash`. + +Convenience class factory methods for creating instances may precede the +`NSObject` methods. + +### Initialization + +Don't initialize instance variables to `0` or `nil` in the `init` method; doing +so is redundant. + +All instance variables for a newly allocated object are [initialized +to](https://developer.apple.com/library/mac/documentation/General/Conceptual/CocoaEncyclopedia/ObjectAllocation/ObjectAllocation.html) +`0` (except for isa), so don't clutter up the init method by re-initializing +variables to `0` or `nil`. + +### Instance Variables In Headers Should Be @protected or @private + +Instance variables should typically be declared in implementation files or +auto-synthesized by properties. When ivars are declared in a header file, they +should be marked `@protected` or `@private`. + +```objectivec +// GOOD: + +@interface MyClass : NSObject { + @protected + id _myInstanceVariable; +} +@end +``` + +### Avoid +new + +Do not invoke the `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. + +### Keep the Public API Simple + +Keep your class simple; avoid "kitchen-sink" APIs. If a method doesn't need to +be public, keep it out of the public interface. + +Unlike C++, Objective-C doesn't differentiate between public and private +methods; any message may be sent to an object. 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. + +Since internal methods are not really private, it's easy to 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. + +### #import and #include + +`#import` Objective-C and Objective-C++ headers, and `#include` C/C++ headers. + +Choose between `#import` and `#include` based on the language of the header that +you are including. + + +When including a header that uses Objective-C or Objective-C++, use `#import`. +When including a standard C or C++ header, use `#include`. +The header should provide its own `#define` guard. + +### Order of Includes + +The standard order for header inclusion is the related header, operating system +headers, language library headers, and finally groups of headers for other +dependencies. + +The related header precedes others to ensure it has no hidden dependencies. +For implementation files the related header is the header file. +For test files the related header is the header containing the tested interface. + +A blank line may separate logically distinct groups of included headers. + +Import headers using their path relative to the project's source directory. + +```objectivec +// GOOD: + +#import "ProjectX/BazViewController.h" + +#import + +#include +#include + +#include "base/basictypes.h" +#include "base/integral_types.h" +#include "util/math/mathutil.h" + +#import "ProjectX/BazModel.h" +#import "Shared/Util/Foo.h" +``` + +### Use Umbrella Headers for System Frameworks + +Import umbrella headers for system frameworks and system libraries rather than +include individual files. + +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` or `#import` rather than `#include` for Objective-C frameworks. + +```objectivec +// GOOD: + +@import UIKit; // GOOD. +#import // GOOD. +``` + +```objectivec +// AVOID: + +#import // AVOID. +#import +... +``` + +### Avoid Accessors During init and dealloc + +Instance subclasses may be in an inconsistent state during init and dealloc +method execution, so code in those methods should avoid invoking accessors on +self. + +Subclasses have not yet been initialized or have already deallocated when init +and dealloc methods execute, making accessor methods on self potentially +unreliable. Whenever practical, directly assign to and release ivars in those +methods rather than rely on accessors. + +```objectivec +// GOOD: + +- (instancetype)init { + self = [super init]; + if (self) { + _bar = 23; // GOOD. + } + return self; +} +``` + +```objectivec +// AVOID: + +- (instancetype)init { + self = [super init]; + if (self) { + self.bar = 23; // AVOID. + } + return self; +} +``` + +```objectivec +// GOOD: + +- (void)dealloc { + [_notifier removeObserver:self]; // GOOD. +} +``` + +```objectivec +// AVOID: + +- (void)dealloc { + [self removeNotifications]; // AVOID. +} +``` + +### Setters copy NSStrings + +Setters taking an `NSString` should always copy the string it accepts. This is +often also appropriate for collections like `NSArray` and `NSDictionary`. + +Never just retain the string, as it may be a `NSMutableString`. This avoids the +caller changing it under you without your knowledge. + +Code receiving and holding collection objects should also consider that the +passed collection may be mutable, and thus the collection could be more safely +held as a copy or mutable copy of the original. + +```objectivec +// GOOD: + +@property(nonatomic, copy) NSString *name; + +- (void)setZigfoos:(NSArray *)zigfoos { + // Ensure that we're holding an immutable collection. + _zigfoos = [zigfoos copy]; +} +``` + +### Use Lightweight Generics to Document Contained Types + +All projects compiling on Xcode 7 or newer versions should make use of the +Objective-C lightweight generics notation to type contained objects. + +Every `NSArray`, `NSDictionary`, or `NSSet` reference should be declared using +lightweight generics for improved type safety and to explicitly document usage. + +```objectivec +// GOOD: + +@property(nonatomic, copy) NSArray *locations; +@property(nonatomic, copy, readonly) NSSet *identifiers; + +NSMutableArray *mutableLocations = [otherObject.locations mutableCopy]; +``` + +If the fully-annotated types become complex, consider using a typedef to +preserve readability. + +```objectivec +// GOOD: + +typedef NSSet *> TimeZoneMappingSet; +TimeZoneMappingSet *timeZoneMappings = [TimeZoneMappingSet setWithObjects:...]; +``` + +Use the most descriptive common superclass or protocol available. In the most +generic case when nothing else is known, declare the collection to be explicitly +heterogenous using id. + +```objectivec +// GOOD: + +@property(nonatomic, copy) NSArray *unknowns; +``` + +### Avoid Throwing Exceptions + +Don't `@throw` Objective-C exceptions, but you should be prepared to catch them +from third-party or OS calls. + +This follows the recommendation to use error objects for error delivery in +[Apple's Introduction to Exception Programming Topics for +Cocoa](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Exceptions/Exceptions.html). + +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. + +### `nil` Checks + +Use `nil` checks for logic flow only. + +Use `nil` pointer checks for logic flow of the application, not for preventing +crashes when sending messages. Sending a message to `nil` [reliably +returns](http://www.sealiesoftware.com/blog/archive/2012/2/29/objc_explain_return_value_of_message_to_nil.html) +`nil` as a pointer, zero as an integer or floating-point value, structs +initialized to `0`, and `_Complex` values equal to `{0, 0}`. + +Note that this applies to `nil` as a message target, not as a parameter value. +Individual methods may or may not safely handle `nil` parameter values. + +Note too that this is distinct from checking C/C++ pointers and block 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 Pitfalls + +Be careful when converting general integral values to `BOOL`. Avoid comparing +directly with `YES`. + +`BOOL` in OS X and in 32-bit iOS builds is defined as a signed `char`, so it may +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` that could, depending on +the value of the last byte of the integer value, still result in a `NO` value. +When converting a general integral value to a `BOOL` use ternary 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). 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 +ternary operator. + +```objectivec +// AVOID: + +- (BOOL)isBold { + return [self fontTraits] & NSFontBoldTrait; // AVOID. +} +- (BOOL)isValid { + return [self stringValue]; // AVOID. +} +``` + +```objectivec +// GOOD: + +- (BOOL)isBold { + return ([self fontTraits] & NSFontBoldTrait) ? YES : NO; +} +- (BOOL)isValid { + return [self stringValue] != nil; +} +- (BOOL)isEnabled { + return [self isValid] && [self isBold]; +} +``` + +Also, don't directly compare `BOOL` variables directly with `YES`. Not only is +it harder to read for those well-versed in C, but the first point above +demonstrates that return values may not always be what you expect. + +```objectivec +// AVOID: + +BOOL great = [foo isGreat]; +if (great == YES) { // AVOID. + // ...be great! +} +``` + +```objectivec +// GOOD: + +BOOL great = [foo isGreat]; +if (great) { // GOOD. + // ...be great! +} +``` + +### Interfaces Without Instance Variables + +Omit the empty set of braces on interfaces that do not declare any instance +variables. + +```objectivec +// GOOD: + +@interface MyClass : NSObject +// Does a lot of stuff. +- (void)fooBarBam; +@end +``` + +```objectivec +// AVOID: + +@interface MyClass : NSObject { +} +// Does a lot of stuff. +- (void)fooBarBam; +@end +``` + +## Cocoa Patterns + +### Delegate Pattern + +Delegates, target objects, and block pointers should not be retained when doing +so would create a retain cycle. + +To avoid causing a retain cycle, a delegate or target pointer should be released +as soon as it is clear there will no longer be a need to message the object. + +If there is no clear time at which the delegate or target pointer is no longer +needed, the pointer should only be retained weakly. + +Block pointers cannot be retained weakly. To avoid causing retain cycles in the +client code, block pointers should be used for callbacks only where they can be +explicitly released after they have been called or once they are no longer +needed. Otherwise, callbacks should be done via weak delegate or target +pointers. + +## Objective-C++ + +### Style Matches the Language + +Within an Objective-C++ source file, follow the style for the language of the +function or method you're implementing. 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. + +For code in an `@implementation` block, use the Objective-C naming rules. For +code in a method of a C++ class, use the C++ naming rules. + +For code in an Objective-C++ file outside of a class implementation, be +consistent within the file. + +```objectivec++ +// GOOD: + +// file: cross_platform_header.h + +class CrossPlatformAPI { + public: + ... + int DoSomethingPlatformSpecific(); // impl on each platform + private: + int an_instance_var_; +}; + +// file: mac_implementation.mm +#include "cross_platform_header.h" + +// A typical Objective-C class, using Objective-C naming. +@interface MyDelegate : NSObject { + @private + int _instanceVar; + CrossPlatformAPI* _backEndObject; +} + +- (void)respondToSomething:(id)something; + +@end + +@implementation MyDelegate + +- (void)respondToSomething:(id)something { + // bridge from Cocoa through our C++ backend + _instanceVar = _backEndObject->DoSomethingPlatformSpecific(); + NSString* tempString = [NSString stringWithFormat:@"%d", _instanceVar]; + NSLog(@"%@", tempString); +} + +@end + +// The platform-specific implementation of the C++ class, using +// C++ naming. +int CrossPlatformAPI::DoSomethingPlatformSpecific() { + NSString* temp_string = [NSString stringWithFormat:@"%d", an_instance_var_]; + NSLog(@"%@", temp_string); + return [temp_string intValue]; +} +``` + +Projects may opt to use an 80 column line length limit for consistency with +Google's C++ style guide. + +## Objective-C Style Exceptions + +### Indicating style exceptions + +Lines of code that are not expected to adhere to these style recommendations +require `// NOLINT` at the end of the line or `// NOLINTNEXTLINE` at the end of +the previous line. Sometimes it is required that parts of Objective-C code must +ignore these style recommendations (for example code may be machine generated or +code constructs are such that its not possible to style correctly). + +A `// NOLINT` comment on that line or `// NOLINTNEXTLINE` on the previous line +can be used to indicate to the reader that code is intentionally ignoring style +guidelines. In addition these annotations can also be picked up by automated +tools such as linters and handle code correctly. Note that there is a single +space between `//` and `NOLINT*`. diff --git a/objcguide.xml b/objcguide.xml deleted file mode 100644 index 1fb404b36..000000000 --- a/objcguide.xml +++ /dev/null @@ -1,1884 +0,0 @@ - - - - -

- -Revision 2.59 -

- - - -
-
- Mike Pinkerton
- Greg Miller
- Dave MacLachlan -
-
- - - - - - - This style guide contains many details that are initially - hidden from view. They are marked by the triangle icon, which you - see here on your left. Click it now. - You should see "Hooray" appear below. - - -

- 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 - - Programming with Objective-C - . -

-
-
- - - -

- 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 -

- - - #import <Foundation/Foundation.h> - - // A sample class demonstrating good Objective-C style. All interfaces, - // categories, and protocols (read: all non-trivial top-level declarations - // in a header) MUST be commented. Comments must also be adjacent to the - // object they're documenting. - // - // (no blank line between this comment and the interface) - @interface Foo : NSObject - - // Returns an autoreleased instance of Foo. See -initWithBar: for details - // about |bar|. - + (instancetype)fooWithBar:(NSString *)bar; - - // Designated initializer. |bar| is a thing that represents a thing that - // does a thing. - - (instancetype)initWithBar:(NSString *)bar; - - // Gets and sets |_bar|. - - (NSString *)bar; - - (void)setBar:(NSString *)bar; - - // Does some work with |blah| and returns YES if the work was completed - // successfully, and NO otherwise. - - (BOOL)doWorkWithBlah:(NSString *)blah; - - @end - - -

- 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. -

- - - #import "Foo.h" - - - @implementation Foo { - NSString *_bar; - NSString *_foo; - } - - + (instancetype)fooWithBar:(NSString *)bar { - return [[[self alloc] initWithBar:bar] autorelease]; - } - - // Must always override super's designated initializer. - - (instancetype)init { - return [self initWithBar:nil]; - } - - - (instancetype)initWithBar:(NSString *)bar { - if ((self = [super init])) { - _bar = [bar copy]; - _bam = [[NSString alloc] initWithFormat:@"hi %d", 3]; - } - return self; - } - - - (void)dealloc { - [_bar release]; - [_bam release]; - [super dealloc]; - } - - - (NSString *)bar { - return _bar; - } - - - (void)setBar:(NSString *)bar { - [_bar autorelease]; - _bar = [bar copy]; - } - - - (BOOL)doWorkWithBlah:(NSString *)blah { - // ... - return NO; - } - - @end - - -

- 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. -

- -
- - - - - - Use only spaces, and indent 2 spaces at a time. - - -

- 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. -

- -
- - - - The maximum line length for Objective-C and Objective-C++ files is 100 - columns. Projects may opt to use an 80 column limit for consistency with - the C++ style guide. - - -

- You can make violations easier to spot by enabling Preferences > - Text Editing > Page guide at column: 100 in Xcode. -

- -
- - - - One space should be used between the - or + - and the return type, and no spacing in the parameter list except between - parameters. - - -

- Methods should look like this: -

- - - (void)doSomethingWithString:(NSString *)theString { - ... - } - -

- 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. -

- - - (void)doSomethingWith:(GTMFoo *)theFoo - rect:(NSRect)theRect - interval:(float)theInterval { - ... - } - -

- When the first keyword is shorter than the others, indent the later - lines by at least four spaces, maintaining colon alignment: -

- - - (void)short:(GTMFoo *)theFoo - longKeyword:(NSRect)theRect - evenLongerKeyword:(float)theInterval - error:(NSError **)theError { - ... - } - - -
- - - - Method invocations should be formatted much like method declarations. - When there's a choice of formatting styles, follow the convention - already used in a given source file. - - -

- Invocations should have all arguments on one line: -

- - [myObject doFooWith:arg1 name:arg2 error:arg3]; - -

- or have one argument per line, with colons aligned: -

- - [myObject doFooWith:arg1 - name:arg2 - error:arg3]; - -

- Don't use any of these styles: -

- - [myObject doFooWith:arg1 name:arg2 // some lines with >1 arg - error:arg3]; - - [myObject doFooWith:arg1 - name:arg2 error:arg3]; - - [myObject doFooWith:arg1 - name:arg2 // aligning keywords instead of colons - error:arg3]; - - -

- 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: -

- - [myObj short:arg1 - longKeyword:arg2 - evenLongerKeyword:arg3 - error:arg4]; - -

- Invocations containing inlined blocks may have - their segments left-aligned at a four space indent. -

- -
- - - - The @public and @private access modifiers - should be indented by 1 space. - - -

- This is similar to public, private, and - protected in C++. -

- - @interface MyClass : NSObject { - @public - ... - @private - ... - } - @end - - -
- - - - Format exceptions with each @ 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. -

- - @try { - foo(); - } - @catch (NSException *ex) { - bar(ex); - } - @finally { - baz(); - } - - -
- - - - There should not be a space between the type identifier and the name - of the protocol encased in angle brackets. - - -

- This applies to class declarations, instance variables, and method - declarations. For example: -

- - @interface MyProtocoledClass : NSObject<NSWindowDelegate> { - @private - id<MyFancyDelegate> _delegate; - } - - (void)setDelegate:(id<MyFancyDelegate>)aDelegate; - @end - - -
- - - - Code inside blocks should be indented four spaces. - - -

- There are several appropriate style rules, depending on how long the - block is: -

-
    -
  • If the block can fit on one line, no wrapping is necessary.
  • -
  • - If it has to wrap, the closing brace should line up with the first - character of the line on which the block is declared. -
  • -
  • Code within the block should be indented four spaces.
  • -
  • - If the block is large, e.g. more than 20 lines, it is recommended to - move it out-of-line into a local variable. -
  • -
  • - If the block takes no parameters, there are no spaces between the - characters ^{. If the block takes parameters, there is no - space between the ^( characters, but there is one space - between the ) { characters. -
  • -
  • - Invocations containing inlined blocks may have their segments - left-aligned at a four-space indent. This helps when invocations - contain multiple inlined blocks. -
  • -
  • - Two space indents inside blocks are also allowed, but should only - be used when it's consistent with the rest of the project's code. -
  • -
- - // The entire block fits on one line. - [operation setCompletionBlock:^{ [self onOperationDone]; }]; - - // The block can be put on a new line, indented four spaces, with the - // closing brace aligned with the first character of the line on which - // block was declared. - [operation setCompletionBlock:^{ - [self.delegate newDataAvailable]; - }]; - - // Using a block with a C API follows the same alignment and spacing - // rules as with Objective-C. - dispatch_async(_fileIOQueue, ^{ - NSString* path = [self sessionFilePath]; - if (path) { - // ... - } - }); - - // An example where the parameter wraps and the block declaration fits - // on the same line. Note the spacing of |^(SessionWindow *window) {| - // compared to |^{| above. - [[SessionService sharedService] - loadWindowWithCompletionBlock:^(SessionWindow *window) { - if (window) { - [self windowDidLoad:window]; - } else { - [self errorLoadingWindow]; - } - }]; - - // An example where the parameter wraps and the block declaration does - // not fit on the same line as the name. - [[SessionService sharedService] - loadWindowWithCompletionBlock: - ^(SessionWindow *window) { - if (window) { - [self windowDidLoad:window]; - } else { - [self errorLoadingWindow]; - } - }]; - - // Large blocks can be declared out-of-line. - void (^largeBlock)(void) = ^{ - // ... - }; - [_operationQueue addOperationWithBlock:largeBlock]; - - // An example with multiple inlined blocks in one invocation. - [myObject doSomethingWith:arg1 - firstBlock:^(Foo *a) { - // ... - } - secondBlock:^(Bar *b) { - // ... - }]; - - -
- - - - For projects using Xcode 4.4 or later and clang, the use of container - (array and dictionary) literals is encouraged. If split across multiple - lines, the contents should be indented two spaces. - - -

- If the collection fits on one line, put a single space after the opening - and before the closing brackets. -

- - NSArray* array = @[ [foo description], @"Another String", [bar description] ]; - - NSDictionary* dict = @{ NSForegroundColorAttributeName : [NSColor redColor] }; - -

- Not: -

- - NSArray* array = @[[foo description], [bar description]]; - - NSDictionary* dict = @{NSForegroundColorAttributeName: [NSColor redColor]}; - - -

- If the collection spans more than a single line, place the opening - bracket on the same line as the declaration, indent the body by two - spaces, and place the closing bracket on a new line that is indented to - the same level as the opening bracket. -

- - NSArray* array = @[ - @"This", - @"is", - @"an", - @"array" - ]; - - NSDictionary* dictionary = @{ - NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12], - NSForegroundColorAttributeName : fontColor - }; - - -

- For dictionary literals, there should be one space before the colon and - at least one space after it (to optionally align the values). -

- - NSDictionary* option1 = @{ - NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12], - NSForegroundColorAttributeName : fontColor - }; - - NSDictionary* option2 = @{ - NSFontAttributeName : [NSFont fontWithName:@"Arial" size:12], - NSForegroundColorAttributeName : fontColor - }; - -

- The following are all incorrect: -

- - // There should be a space before the colon. - NSDictionary* wrong = @{ - AKey: @"b", - BLongerKey: @"c", - }; - - // The items should each be on a new line, or the entire expression - // should fit on one line. - NSDictionary* alsoWrong= @{ AKey : @"a", - BLongerKey : @"b" }; - - // There should be no variable space before the colon, only after. - NSDictionary* stillWrong = @{ - AKey : @"b", - BLongerKey : @"c", - }; - - -
-
- - - -

- 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 names should reflect the name of the class implementation that - they contain—including case. Follow the convention that your - - project - uses. - - -

- File extensions should be as follows: -

- - - - - - - - - - - - - - - - - - - - - -
.hC/C++/Objective-C header file
.mObjective-C implementation file
.mmObjective-C++ implementation file
.ccPure C++ implementation file
.cC implementation file
-

- File names for categories should include the name of the class being - extended, e.g. GTMNSString+Utils.h or - GTMNSTextView+Autocomplete.h -

- -
- - - - Within a source file, Objective-C++ follows the style of the - function/method you're implementing. - - -

- 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. -

- - // file: cross_platform_header.h - - class CrossPlatformAPI { - public: - ... - int DoSomethingPlatformSpecific(); // impl on each platform - private: - int an_instance_var_; - }; - - // file: mac_implementation.mm - #include "cross_platform_header.h" - - // A typical Objective-C class, using Objective-C naming. - @interface MyDelegate : NSObject { - @private - int _instanceVar; - CrossPlatformAPI* _backEndObject; - } - - (void)respondToSomething:(id)something; - @end - @implementation MyDelegate - - (void)respondToSomething:(id)something { - // bridge from Cocoa through our C++ backend - _instanceVar = _backEndObject->DoSomethingPlatformSpecific(); - NSString* tempString = [NSString stringWithFormat:@"%d", _instanceVar]; - NSLog(@"%@", tempString); - } - @end - - // The platform-specific implementation of the C++ class, using - // C++ naming. - int CrossPlatformAPI::DoSomethingPlatformSpecific() { - NSString* temp_string = [NSString stringWithFormat:@"%d", an_instance_var_]; - NSLog(@"%@", temp_string); - return [temp_string intValue]; - } - - -
- - - - Class names (along with category and protocol names) should start as - uppercase and use mixed case to delimit words. - - -

- When designing code to be shared across multiple applications, - prefixes are acceptable and recommended (e.g. GTMSendMessage). - Prefixes are also recommended for classes of large applications that - depend on external libraries. -

- - -
- - - - Category names should start with a 2 or 3 character prefix - identifying the category as part of a project or open for general - use. The category name should incorporate the name of the class it's - extending. - - -

- 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. -

- - // Extending a framework class: - @interface NSString (GTMStringParsingAdditions) - - (NSString *)gtm_foobarString; - @end - - // Making your methods and properties private: - @interface FoobarViewController () - @property(nonatomic, retain) NSView *dongleView; - - (void)performLayout; - @end - - -
- - - - Method names should start as lowercase and then use mixed case. - Each named parameter should also start as lowercase. - - -

- 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: - - - (id)getDelegate; // AVOID - - - - (id)delegate; // GOOD - -

-

- This is for Objective-C methods only. C++ method names and functions - continue to follow the rules set in the C++ style guide. -

- -
- - - - Variables names start with a lowercase and use mixed case to delimit - words. Instance variables have leading underscores. For example: - myLocalVariable, _myInstanceVariable. - - - -

- 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: -

- - int w; - int nerr; - int nCompConns; - tix = [[NSMutableArray alloc] init]; - obj = [someObject object]; - p = [network port]; - - - int numErrors; - int numCompletedConnections; - tickets = [[NSMutableArray alloc] init]; - userInfo = [someObject object]; - port = [network port]; - -
- - -

- 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. For example: -

- - const int kNumberOfFiles = 12; - NSString *const kUserKey = @"kUserKey"; - enum DisplayTinge { - kDisplayTingeGreen = 1, - kDisplayTingeBlue = 2 - }; - -

- Because Objective-C does not provide namespacing, constants with global - scope should have an appropriate prefix to minimize the chance of name - collision, typically like kClassNameFoo. -

-
- -
- -
- - - -

- 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. -

- - - - A file may optionally start with a description of its contents. - - - -

- Every file should contain the following items, in order: -

    -
  • license boilerplate if neccessary. Choose the appropriate - boilerplate for the license used by the project (e.g. - Apache 2.0, BSD, LGPL, GPL).
  • -
  • a basic description of the contents of the file if necessary.
  • -
-

-

- 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. -

- -
- - - - Every interface, category, and protocol declaration should have an - accompanying comment describing its purpose and how it fits into the - larger picture. - - - - // A delegate for NSApplication to handle notifications about app - // launch and shutdown. Owned by the main app controller. - @interface MyAppDelegate : NSObject { - ... - } - @end - -

- 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. -

- -
- - - - Use vertical bars to quote variable names and symbols in comments rather - than quotes or naming the symbol inline. - - -

- 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": -

- - // Sometimes we need |count| to be less than zero. - -

- or when quoting something which already contains quotes -

- - // Remember to call |StringWithoutSpaces("foo bar baz")| - - -
- - - - Make the pointer ownership model as explicit as possible when it falls - outside the most common Objective-C usage idioms. - - - -

- 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 - strong and weak comments 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. -

-

- Examples of strong and weak declarations: - - @interface MyDelegate : NSObject { - @private - IBOutlet NSButton *_okButton; // Normal NSControl; implicitly weak on Mac only - - AnObjcObject* _doohickey; // My doohickey - __weak MyObjcParent *_parent; // So we can send msgs back (owns me) - - // non-NSObject pointers... - CWackyCPPClass *_wacky; // Strong, some cross-platform object - CFDictionaryRef *_dict; // Strong - } - @property(strong, nonatomic) NSString *doohickey; - @property(weak, nonatomic) NSString *parent; - @end - -

-
- -

- Object ownership and lifetime are explicit when using ARC, so no - additional comments are required. -

-
- -
- -
- - - - - - Instance variables should typically be declared in implementation files - or auto-synthesized by properties. When ivars are declared in a header - file, they should be marked @private. - - - - @interface MyClass : NSObject { - @private - id _myInstanceVariable; - } - @end - - - - - - - Comment and clearly identify your designated initializer. - - -

- 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. -

- -
- - - - When writing a subclass that requires an 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. -

- -
- - - - It is strongly recommended and typical practice to place overridden - methods of NSObject at the top of an - @implementation. - - -

- This commonly applies (but is not limited) to the init..., - copyWithZone:, and dealloc methods. - init... methods should be grouped together, followed by - other NSObject methods. -

-

- Convenience class methods for creating instances may precede the - NSObject methods. -

- -
- - - - Don't initialize variables to 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. -

- -
- - - - Do not invoke the 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. -

- -
- - - - Keep your class simple; avoid "kitchen-sink" APIs. If a method doesn't - need to be public, don't make it so. Use a private category to prevent - cluttering the public header. - - -

- 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. -

- - #import "GTMFoo.h" - - @interface GTMFoo (PrivateDelegateHandling) - - (NSString *)doSomethingWithDelegate; // Declare private method - @end - - @implementation GTMFoo (PrivateDelegateHandling) - ... - - (NSString *)doSomethingWithDelegate { - // Implement this method - } - ... - @end - -

- If you are using Objective-C 2.0, you should instead declare your - private category using a class - extension, for example: -

- - @interface GMFoo () { ... } - -

- 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. -

-
    -
  • When including a header that uses Objective-C or Objective-C++, - use #import.
  • -
  • When including a standard C or C++ header, use - #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. -

- - #import <Cocoa/Cocoa.h> - #include <CoreFoundation/CoreFoundation.h> - #import "GTMFoo.h" - #include "base/basictypes.h" - - -
- - - - Include root frameworks over individual files. - - -

- 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. -

- - #import <Foundation/Foundation.h> // good - - - #import <Foundation/NSArray.h> // avoid - #import <Foundation/NSString.h> - ... - - -
- - - - When creating new temporary objects, 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.: -

- - // AVOID (unless you have a compelling performance reason) - MyController* controller = [[MyController alloc] init]; - // ... code here that might return ... - [controller release]; - - - // BETTER - MyController* controller = [[[MyController alloc] init] autorelease]; - - -
- - - - Assignment of objects follows the 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. -

- - - (void)setFoo:(GMFoo *)aFoo { - [_foo autorelease]; // Won't dealloc if |_foo| == |aFoo| - _foo = [aFoo retain]; - } - - -
- - - - Instance subclasses may be in an inconsistent state during - 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. -

- - - (instancetype)init { - self = [super init]; - if (self) { - _bar = [[NSMutableString alloc] init]; // good - } - return self; - } - - - (void)dealloc { - [_bar release]; // good - [super dealloc]; - } - - - - (instancetype)init { - self = [super init]; - if (self) { - self.bar = [NSMutableString string]; // avoid - } - return self; - } - - - (void)dealloc { - self.bar = nil; // avoid - [super dealloc]; - } - - -
- - - - 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. -

- -
- - - - Setters taking an 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. -

- - - (void)setFoo:(NSString *)aFoo { - [_foo autorelease]; - _foo = [aFoo copy]; - } - - -
- - - - Don't @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. -

- -
- - - - - Use nil checks for logic flow only. - - -

- Use nil pointer checks for logic flow of the application, - not for preventing crashes when sending messages. With current compilers - ( - as of LLVM 3.0/Xcode 4.2), sending a message to nil - reliably returns nil as a pointer, zero as an integer or floating-point - value, structs initialized to 0, and _Complex values equal - to {0, 0}. -

-

- Note that this applies to nil as a message target, not as - a parameter value. Individual methods may or may not safely handle - nil parameter values. -

-

- Note too that this is distinct from checking C/C++ pointers and block - 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. -

- -
- - - - Be careful when converting general integral values to 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. -

- - - (BOOL)isBold { - return [self fontTraits] & NSFontBoldTrait; - } - - (BOOL)isValid { - return [self stringValue]; - } - - - - (BOOL)isBold { - return ([self fontTraits] & NSFontBoldTrait) ? YES : NO; - } - - (BOOL)isValid { - return [self stringValue] != nil; - } - - (BOOL)isEnabled { - return [self isValid] && [self isBold]; - } - -

- 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. -

- - BOOL great = [foo isGreat]; - if (great == YES) - // ...be great! - - - BOOL great = [foo isGreat]; - if (great) - // ...be great! - - - -
- - - - Use of the @property directive is preferred, with the following caveat: - properties are an Objective-C 2.0 feature which will limit your code to - running on the iPhone and Mac OS X 10.5 (Leopard) and higher. Dot notation - is allowed only for access to a declared @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. -

- - - @interface MyClass : NSObject - @property(copy, nonatomic) NSString *name; - @end - - @implementation MyClass - // No code required for auto-synthesis, else use: - // @synthesize name = _name; - @end - -
- -

- 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. -

- - @interface MyClass : NSObject { - @private - NSString *_name; - } - @property(copy, nonatomic) NSString *name; - @end - - @implementation MyClass - @synthesize name = _name; - - - (instancetype)init { - ... - } - @end - -
- -

- 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. -

- - NSString *oldName = myObject.name; - myObject.name = @"Alice"; - - - NSArray *array = [[NSArray arrayWithObject:@"hello"] retain]; - - NSUInteger numberOfItems = array.count; // not a property - array.release; // not a property - -
- -
- - - - Omit the empty set of braces on interfaces that do not declare any - instance variables. - - - - @interface MyClass : NSObject - // Does a lot of stuff - - (void)fooBarBam; - @end - - - @interface MyClass : NSObject { - } - // Does a lot of stuff - - (void)fooBarBam; - @end - - - - - - -

- 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. -

-
- - - // Header file - @protocol Thingy - @property(nonatomic, copy) NSString *widgetName; - @end - - @interface Foo : NSObject<Thingy> - // A guy walks into a bar. - @property(nonatomic, copy) NSString *bar; - @end - - // Implementation file - @interface Foo () - @property(nonatomic, retain) NSArray *baz; - @end - - @implementation Foo - @synthesize widgetName = _widgetName; - @end - - -

- 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. - - #if !defined(__has_feature) || !__has_feature(objc_arc) - #error "This file requires ARC support." - #endif - - #import "Foo.h" - - @implementation Foo { - Bar* __weak _bar; - Baz* __unsafe_unretained _baz; - } - // ... - @end - -

- -
- - - -

- 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. - - NSNumber *fortyTwo = @42; - NSNumber *piOverTwo = @(M_PI / 2); - enum { - kMyEnum = 2; - }; - NSNumber *myEnum = @(kMyEnum); - -

- -
-
- - - - - - - Delegate objects should not be retained when doing so would create - a retain cycle. - - -

- A class that implements the delegate pattern should typically: -

    -
  1. - Have an instance variable named _delegate to reference - the delegate. -
  2. -
  3. - Thus, the accessor methods should be named delegate - and setDelegate:. -
  4. -
  5. - The _delegate object should be weak if the class - is typically retained by its delegate, such that a strong delegate - would create a retain cycle. -
  6. -
-

- -
- - - - Separate the model from the view. Separate the controller from the - view and the model. Use @protocols for callback APIs. - - -

-

    -
  • - Separate model from view: don't build assumptions about the - presentation into the model or data source. Keep the interface - between the data source and the presentation abstract. Don't give - the model knowledge of its view. (A good rule of thumb is to ask - yourself if it's possible to have multiple presentations, with - different states, on a single instance of your data source.) -
  • -
  • - Separate controller from view and model: don't put all of the - "business logic" into view-related classes; this makes the code - very unusable. Make controller classes to host this code, but - ensure that the controller classes don't make too many assumptions - about the presentation. -
  • -
  • - Define callback APIs with @protocol, using - @optional if not all the methods are required. -
  • -
-

- -
- -
- - - - - - Trailing underscores were once preferred for instance variable names. - - -

- 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.59 -

- - - -
-Mike Pinkerton
-Greg Miller
-Dave MacLachlan
-
-