From a7fc1ef687ef566c32f81e585a3d7911906324d5 Mon Sep 17 00:00:00 2001 From: Stephane Moore Date: Fri, 17 Aug 2018 18:47:57 -0700 Subject: [PATCH] =?UTF-8?q?[objc]=20Update=20the=20Objective-C=20style=20g?= =?UTF-8?q?uide=20=F0=9F=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- objcguide.md | 888 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 525 insertions(+), 363 deletions(-) diff --git a/objcguide.md b/objcguide.md index 7d965ce..30891ce 100644 --- a/objcguide.md +++ b/objcguide.md @@ -102,11 +102,11 @@ for an `@interface` declaration. + (instancetype)fooWithBar:(Bar *)bar; /** - * Designated initializer. + * Initializes and returns a Foo object using the provided Bar instance. * * @param bar A string that represents a thing that does a thing. */ -- (instancetype)initWithBar:(Bar *)bar; +- (instancetype)initWithBar:(Bar *)bar NS_DESIGNATED_INITIALIZER; /** * Does some work with @c blah. @@ -163,320 +163,16 @@ An example source file, demonstrating the correct commenting and spacing for the @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: +Avoid non-standard abbreviations (including non-standard acronyms and +initialisms). 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: @@ -529,32 +225,60 @@ Extension | Type 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. +class [prefix](#prefixes). File names for categories should include the name of the class being extended, like GTMNSString+Utils.h or NSTextView+GTMAutocomplete.h +### Prefixes + +Prefixes are commonly required in Objective-C to avoid naming collisions in a +global namespace. Classes, protocols, global functions, and global constants +should generally be named with a prefix that begins with a capital letter +followed by one or more capital letters or numbers. + +WARNING: Apple reserves two-letter prefixes—see +[Conventions in Programming with Objective-C](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html)—so +prefixes with a minimum of three characters are considered best practice. + +```objectivec +// GOOD: + +/** An example error domain. */ +extern NSString *GTMExampleErrorDomain; + +/** Gets the default time zone. */ +extern NSTimeZone *GTMGetDefaultTimeZone(void); + +/** An example delegate. */ +@protocol GTMExampleDelegate +@end + +/** An example class. */ +@interface GTMExample : NSObject +@end + +``` + ### 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. +Classes and protocols in code shared across multiple applications must have an +appropriate [prefix](#prefixes) (e.g. GTMSendMessage). Prefixes are recommended, +but not required, for other classes and protocols. -### Category Names +### Category Naming -Category names should start with a 3 character prefix identifying the category -as part of a project or open for general use. +Category names should start with an appropriate [prefix](#prefixes) 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 +Category source file names should begin with the class being extended followed +by a plus sign and the name of the category, e.g., `NSString+GTMParsing.h`. +Methods in a category should be prefixed with a lowercase version of the prefix +used for the category name followed by an underscore (e.g., +`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 @@ -563,9 +287,29 @@ parenthesis of the category. ```objectivec // GOOD: -/** A category that adds parsing functionality to NSString. */ -@interface NSString (GTMNSStringParsingAdditions) -- (NSString *)gtm_parsedString; +// UIViewController+GTMCrashReporting.h + +/** A category that adds metadata to include in crash reports to UIViewController. */ +@interface UIViewController (GTMCrashReporting) + +/** A unique identifier to represent the view controller in crash reports. */ +@property(nonatomic, setter=gtm_setUniqueIdentifier:) int gtm_uniqueIdentifier; + +/** Returns an encoded representation of the view controller's current state. */ +- (nullable NSData *)gtm_encodedState; + +@end +``` + +If a class is not shared with other projects, categories extending it may omit +name prefixes and method name prefixes. + +```objectivec +// GOOD: + +/** This category extends a class that is not shared with other projects. */ +@interface XYZDataObject (Storage) +- (NSString *)storageIdentifier; @end ``` @@ -672,26 +416,24 @@ 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"). +Function names 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); +static BOOL DeleteFile(const char *filename); ``` Because Objective-C does not provide namespacing, non-static functions should -have a prefix that minimizes the chance of a name collision. +have a [prefix](#prefixes) that minimizes the chance of a name collision. ```objectivec // GOOD: -extern NSTimeZone *GTMGetDefaultTimeZone(); +extern NSTimeZone *GTMGetDefaultTimeZone(void); extern NSString *GTMGetURLScheme(NSURL *URL); ``` @@ -735,7 +477,7 @@ class. Constant symbols (const global and static variables and constants created with #define) should use mixed case to delimit words. -Global and file scope constants should have an appropriate prefix. +Global and file scope constants should have an appropriate [prefix](#prefixes). ```objectivec // GOOD: @@ -764,7 +506,8 @@ typedef NS_ENUM(NSInteger, DisplayTinge) { }; ``` -Constants may use a lowercase k prefix when appropriate: +A lowercase k can be used as a standalone prefix for constants of static storage +duration declared within implementation files: ```objectivec // GOOD: @@ -773,8 +516,19 @@ static const int kFileCount = 12; static NSString *const kUserKey = @"kUserKey"; ``` +NOTE: Previous convention was for public constant names to begin with a +lowercase k followed by a project-specific [prefix](#prefixes). This practice is +no longer recommended. + ## Types and Declarations +### Method Declarations + +As shown in the [example](#Example), the recommended order +for declarations in an `@interface` declaration are: properties, class methods, +initializers, and then finally instance methods. The class methods section +should begin with any convenience constructors. + ### Local Variables Declare variables in the narrowest practical scopes, and close to their use. @@ -804,9 +558,13 @@ for (meters = 1; meters < 10; meters++) { } ``` -Under Automatic Reference Counting, pointers to Objective-C objects are by -default initialized to `nil`, so explicit initialization to `nil` is not -required. +Under Automatic Reference Counting, strong and weak pointers to Objective-C +objects are automatically initialized to `nil`, so explicit initialization to +`nil` is not required for those common cases. However, automatic initialization +does *not* occur for many Objective-C pointer types, including object pointers +declared with the `__unsafe_unretained` ownership qualifier and CoreFoundation +object pointer types. When in doubt, prefer to initialize all Objective-C +local variables. ### Unsigned Integers @@ -1145,8 +903,7 @@ 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. +include compound statement expressions (e.g. `foo = ({ int x; Bar(&x); x })`). `__attribute__` is an approved exception, as it is used in Objective-C API specifications. @@ -1215,14 +972,11 @@ should be marked `@protected` or `@private`. @end ``` -### Avoid +new +### Do Not Use +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. +`+new` is rarely used and contrasts greatly with initializer usage. Instead, use +`+alloc` and `-init` methods to instantiate retained objects. ### Keep the Public API Simple @@ -1245,13 +999,10 @@ prevent subclasses from unintentionally overriding them. `#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. +C/C++ headers include other C/C++ headers using `#include`. Using `#import` +on C/C++ headers prevents future inclusions using `#include` and could result in +unintended compilation behavior. +C/C++ headers should provide their own `#define` guard. ### Order of Includes @@ -1265,6 +1016,8 @@ For test files the related header is the header containing the tested interface. A blank line may separate logically distinct groups of included headers. +Within each group the includes should be ordered alphabetically. + Import headers using their path relative to the project's source directory. ```objectivec @@ -1451,14 +1204,26 @@ 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 +Avoid `nil` pointer checks that exist only to prevent sending messages to `nil`. +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}`. +```objectivec +// AVOID: + +if (dataSource) { // AVOID. + [dataSource moveItemAtIndex:1 toIndex:0]; +} +``` + +```objectivec +// GOOD: + +[dataSource moveItemAtIndex:1 toIndex:0]; // GOOD. +``` + 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. @@ -1467,6 +1232,54 @@ 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. +### Nullability + +Interfaces can be decorated with nullability annotations to describe how the +interface should be used and how it behaves. Use of nullability regions (e.g., +`NS_ASSUME_NONNULL_BEGIN` and `NS_ASSUME_NONNULL_END`) and explicit nullability +annotations are both accepted. Prefer using the `_Nullable` and `_Nonnull` +keywords over the `__nullable` and `__nonnull` keywords. For Objective-C methods +and properties prefer using the context-sensitive, non-underscored keywords, +e.g., `nonnull` and `nullable`. + +```objectivec +// GOOD: + +/** A class representing an owned book. */ +@interface GTMBook : NSObject + +/** The title of the book. */ +@property(readonly, copy, nonnull) NSString *title; + +/** The author of the book, if one exists. */ +@property(readonly, copy, nullable) NSString *author; + +/** The owner of the book. Setting nil resets to the default owner. */ +@property(copy, null_resettable) NSString *owner; + +/** Initializes a book with a title and an optional author. */ +- (nonnull instancetype)initWithTitle:(nonnull NSString *)title + author:(nullable NSString *)author + NS_DESIGNATED_INITIALIZER; + +/** Returns nil because a book is expected to have a title. */ +- (nullable instancetype)init; + +@end + +/** Loads books from the file specified by the given path. */ +NSArray *_Nullable GTMLoadBooksFromFile(NSString *_Nonnull path); +``` + +```objectivec +// AVOID: + +NSArray *__nullable GTMLoadBooksFromTitle(NSString *__nonnull path); +``` + +Be careful assuming that a pointer is not null based on a non-null qualifier +because the compiler may not guarantee that the pointer is not null. + ### BOOL Pitfalls Be careful when converting general integral values to `BOOL`. Avoid comparing @@ -1479,7 +1292,7 @@ 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 +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 @@ -1610,7 +1423,7 @@ class CrossPlatformAPI { // file: mac_implementation.mm #include "cross_platform_header.h" -// A typical Objective-C class, using Objective-C naming. +/** A typical Objective-C class, using Objective-C naming. */ @interface MyDelegate : NSObject { @private int _instanceVar; @@ -1632,8 +1445,7 @@ class CrossPlatformAPI { @end -// The platform-specific implementation of the C++ class, using -// C++ naming. +/** 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); @@ -1644,6 +1456,356 @@ int CrossPlatformAPI::DoSomethingPlatformSpecific() { Projects may opt to use an 80 column line length limit for consistency with Google's C++ style guide. +## 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 a method declaration does not fit on a single line, put each parameter on its +own line. All lines except the first should be indented at least four spaces. +Colons before parameters should be aligned on all lines. If the colon before the +parameter on the first line of a method declaration is positioned such that +colon alignment would cause indentation on a subsequent line to be less than +four spaces, then colon alignment is only required for all lines except the +first. + +```objectivec +// GOOD: + +- (void)doSomethingWithFoo:(GTMFoo *)theFoo + rect:(NSRect)theRect + interval:(float)theInterval { + ... +} + +- (void)shortKeyword:(GTMFoo *)theFoo + longerKeyword:(NSRect)theRect + someEvenLongerKeyword:(float)theInterval + error:(NSError **)theError { + ... +} + +- (id) + adaptivePresentationControllerDelegateForViewController:(UIViewController *)viewController; + +- (void)presentWithAdaptivePresentationControllerDelegate: + (id)delegate; +``` + +### Function Declarations and Definitions + +Prefer putting the return type on the same line as the function name and append +all parameters on the same line if they will fit. Wrap parameter lists which do +not fit on a single line as you would wrap arguments in a [function +call](#Function_Calls). + +```objectivec +// GOOD: + +NSString *GTMVersionString(int majorVersion, minorVersion) { + ... +} + +void GTMSerializeDictionaryToFileOnDispatchQueue( + NSDictionary *dictionary, + NSString *filename, + dispatch_queue_t queue) { + ... +} +``` + +Function declarations and definitions should also satisfy the following +conditions: + +* The opening parenthesis must always be on the same line as the function + name. +* If you cannot fit the return type and the function name on a single line, + break between them and do not indent the function name. +* There should never be a space before the opening parenthesis. +* There should never be a space between function parentheses and parameters. +* The open curly brace is always on the end of the last line of the function + declaration, not the start of the next line. +* The close curly brace is either on the last line by itself or on the same + line as the open curly brace. +* There should be a space between the close parenthesis and the open curly + brace. +* All parameters should be aligned if possible. +* Function scopes should be indented 2 spaces. +* Wrapped parameters should have a 4 space indent. + +### 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 { // The else goes on the same line as the closing brace. + 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](#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. + ## Objective-C Style Exceptions ### Indicating style exceptions