From 0a326efbe073f37a2a6405ccc8f9fcde468f5abd Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 17 Jan 2025 10:28:17 -0500 Subject: [PATCH] objc: export latest version PiperOrigin-RevId: 716659780 --- objcguide.md | 1037 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 800 insertions(+), 237 deletions(-) diff --git a/objcguide.md b/objcguide.md index a37cc8d..905f136 100644 --- a/objcguide.md +++ b/objcguide.md @@ -1,19 +1,17 @@ # 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. +> is one of the primary development languages for applications on Apple +> platforms. > > 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. +> Objective-C++) coding guidelines and practices. 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 @@ -22,6 +20,7 @@ > Objective-C](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html). + ## Principles ### Optimize for the reader, not the writer @@ -63,7 +62,9 @@ explains the rules we don’t have, rather than the rules we do: for example, go contravenes many of the following principles, but is not discussed due to its extreme rarity. -## Example + + +## 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. @@ -71,7 +72,7 @@ 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. -```objectivec +```objectivec // GOOD: #import @@ -122,7 +123,7 @@ for an `@interface` declaration. An example source file, demonstrating the correct commenting and spacing for the `@implementation` of an interface. -```objectivec +```objectivec // GOOD: #import "Shared/Util/Foo.h" @@ -148,7 +149,7 @@ An example source file, demonstrating the correct commenting and spacing for the _bar = [bar copy]; _string = [[NSString alloc] initWithFormat:@"hi %d", 3]; _attributes = @{ - @"color" : [UIColor blueColor], + @"color" : UIColor.blueColor, @"hidden" : @NO }; } @@ -163,7 +164,9 @@ An example source file, demonstrating the correct commenting and spacing for the @end ``` -## Naming + + +## Naming Names should be as descriptive as possible, within reason. Follow standard [Objective-C naming @@ -174,7 +177,7 @@ 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 +```objectivec // GOOD: // Good names. @@ -186,7 +189,7 @@ port = [network port]; NSDate *gAppLaunchDate; ``` -```objectivec +```objectivec // AVOID: // Names to avoid. @@ -199,20 +202,35 @@ 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. +for acronyms and [initialisms](https://en.wikipedia.org/wiki/Initialism) within +(including at the beginning of) 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 + + +### Inclusive Language + +In all code, including naming and comments, use inclusive language and avoid +terms that other programmers might find disrespectful or offensive (such as +"master" and "slave", "blacklist" and "whitelist", or "redline"), even if the +terms also have an ostensibly neutral meaning. Similarly, use gender-neutral +language unless you're referring to a specific person (and using their +pronouns). For example, use "they"/"them"/"their" for people of unspecified +gender (even when singular), and "it"/"its" for non-people. + + + + +### 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 @@ -241,14 +259,14 @@ 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 +```objectivec // GOOD: /** An example error domain. */ -extern NSString *GTMExampleErrorDomain; +GTM_EXTERN NSString *GTMExampleErrorDomain; /** Gets the default time zone. */ -extern NSTimeZone *GTMGetDefaultTimeZone(void); +GTM_EXTERN NSTimeZone *GTMGetDefaultTimeZone(void); /** An example delegate. */ @protocol GTMExampleDelegate @@ -260,7 +278,9 @@ extern NSTimeZone *GTMGetDefaultTimeZone(void); ``` -### Class Names + + +### Class Names Class names (along with category and protocol names) should start as uppercase and use mixed case to delimit words. @@ -269,7 +289,9 @@ 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 Naming + + +### Category Naming Category names should start with an appropriate [prefix](#prefixes) identifying the category as part of a project or open for general use. @@ -284,7 +306,7 @@ Objective-C's global namespace. There should be a single space between the class name and the opening parenthesis of the category. -```objectivec +```objectivec // GOOD: // UIViewController+GTMCrashReporting.h @@ -304,7 +326,7 @@ parenthesis of the category. If a class is not shared with other projects, categories extending it may omit name prefixes and method name prefixes. -```objectivec +```objectivec // GOOD: /** This category extends a class that is not shared with other projects. */ @@ -313,13 +335,15 @@ name prefixes and method name prefixes. @end ``` -### Objective-C Method Names + + +### 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 +```objectivec // GOOD: + (NSURL *)URLWithString:(NSString *)URLString; @@ -334,7 +358,7 @@ 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 +```objectivec // GOOD: - (void)addTarget:(id)target action:(SEL)action; // GOOD; no conjunction needed @@ -343,31 +367,38 @@ behavior of the method. withAttributedString:(NSAttributedString *)attributedString; // GOOD. ``` -A method that returns an object should have a name beginning with a noun -identifying the object returned: +If the method returns an attribute of the receiver, name the method after the +attribute. -```objectivec +```objectivec // GOOD: +/** Returns this instance's sandwich. */ - (Sandwich *)sandwich; // GOOD. + +- (CGFloat)height; // GOOD. + +// GOOD; Returned value is not an attribute. +- (UIBackgroundTaskIdentifier)beginBackgroundTask; ``` -```objectivec +```objectivec // AVOID: -- (Sandwich *)makeSandwich; // AVOID. +- (CGFloat)calculateHeight; // AVOID. +- (id)theDelegate; // 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 +```objectivec // GOOD: - (id)delegate; // GOOD. ``` -```objectivec +```objectivec // AVOID: - (id)getDelegate; // AVOID. @@ -378,30 +409,31 @@ 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 +```objectivec // GOOD: @property(nonatomic, getter=isGlorious) BOOL glorious; -- (BOOL)isGlorious; +// The method for the getter of the property above is: +// - (BOOL)isGlorious; BOOL isGood = object.glorious; // GOOD. BOOL isGood = [object isGlorious]; // GOOD. ``` -```objectivec +```objectivec // AVOID: BOOL isGood = object.isGlorious; // AVOID. ``` -```objectivec +```objectivec // GOOD: NSArray *frogs = [NSArray arrayWithObject:frog]; NSEnumerator *enumerator = [frogs reverseObjectEnumerator]; // GOOD. ``` -```objectivec +```objectivec // AVOID: NSEnumerator *enumerator = frogs.reverseObjectEnumerator; // AVOID. @@ -414,13 +446,15 @@ 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 + + +### Function Names 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 +```objectivec // GOOD: static void AddTableEntry(NSString *tableEntry); @@ -430,14 +464,16 @@ static BOOL DeleteFile(const char *filename); Because Objective-C does not provide namespacing, non-static functions should have a [prefix](#prefixes) that minimizes the chance of a name collision. -```objectivec +```objectivec // GOOD: -extern NSTimeZone *GTMGetDefaultTimeZone(void); -extern NSString *GTMGetURLScheme(NSURL *URL); +GTM_EXTERN NSTimeZone *GTMGetDefaultTimeZone(void); +GTM_EXTERN NSString *GTMGetURLScheme(NSURL *URL); ``` -### Variable Names + + +### Variable Names Variable names typically start with a lowercase and use mixed case to delimit words. @@ -446,7 +482,9 @@ Instance variables have leading underscores. File scope or global variables have a prefix `g`. For example: `myLocalVariable`, `_myInstanceVariable`, `gMyGlobalVariable`. -#### Common Variable Names + + +#### 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 @@ -455,13 +493,15 @@ 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 +```objectivec // GOOD: static int gGlobalCounter; ``` -#### Instance Variables + + +#### Instance Variables Instance variable names are mixed case and should be prefixed with an underscore, like `_usernameTextField`. @@ -472,21 +512,27 @@ new code in order to maintain consistency within the project codebase. Consistency of prefix or suffix underscores should be maintained within each class. -#### Constants + + +#### Constants 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](#prefixes). -```objectivec +```objectivec // GOOD: -extern NSString *const GTLServiceErrorDomain; +/** The domain for GTL service errors. */ +GTL_EXTERN NSString *const GTLServiceErrorDomain; -typedef NS_ENUM(NSInteger, GTLServiceError) { +/** An enumeration of GTL service error codes. */ +typedef NS_ENUM(int32_t, GTLServiceError) { + /** An error code indicating that a query result was missing. */ GTLServiceErrorQueryResultMissing = -3000, - GTLServiceErrorWaitTimedOut = -3001, + /** An error code indicating that the query timed out. */ + GTLServiceErrorQueryTimedOut = -3001, }; ``` @@ -497,10 +543,11 @@ typically like `ClassNameConstantName` or `ClassNameEnumName`. For interoperability with Swift code, enumerated values should have names that extend the typedef name: -```objectivec +```objectivec // GOOD: -typedef NS_ENUM(NSInteger, DisplayTinge) { +/** An enumeration of supported display tinges. */ +typedef NS_ENUM(int32_t, DisplayTinge) { DisplayTingeGreen = 1, DisplayTingeBlue = 2, }; @@ -509,7 +556,7 @@ typedef NS_ENUM(NSInteger, DisplayTinge) { A lowercase k can be used as a standalone prefix for constants of static storage duration declared within implementation files: -```objectivec +```objectivec // GOOD: static const int kFileCount = 12; @@ -520,21 +567,27 @@ 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 +## 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 + + +### Local Variables Declare variables in the narrowest practical scopes, and close to their use. Initialize variables in their declarations. -```objectivec +```objectivec // GOOD: CLLocation *location = [self lastKnownLocation]; @@ -548,7 +601,7 @@ 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 +```objectivec // AVOID: int meters; // AVOID. @@ -566,7 +619,31 @@ 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 +### Static Variables + +When file scope variable/constant declarations in an implementation file do not +need to be referenced outside that file, declare them static (or in an anonymous +namespace in Objective-C++). Do not declare file scope variables or constants +with static storage duration (or in anonymous namespaces in Objective-C++) in .h +files. + +```objectivec +// GOOD: + +// file: Foo.m +static const int FOORequestLimit = 5; +``` + +```objectivec +// AVOID: + +// file: Foo.h +static const int FOORequestLimit = 5; // AVOID. +``` + + + +### Unsigned Integers Avoid unsigned integers except when matching types used by system interfaces. @@ -574,32 +651,32 @@ 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 +```objectivec // GOOD: NSUInteger numberOfObjects = array.count; -for (NSInteger counter = numberOfObjects - 1; counter > 0; --counter) +for (NSInteger counter = numberOfObjects - 1; counter >= 0; --counter) ``` -```objectivec +```objectivec // AVOID: -for (NSUInteger counter = numberOfObjects - 1; counter > 0; --counter) // 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 with Inconsistent Sizes -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. +Be aware that types long, NSInteger, NSUInteger and CGFloat have sizes that +differ in 32- and 64-bit builds. Their use is appropriate when matching system +interfaces but should be avoided when dealing with APIs that +require exact sizing, e.g., proto APIs. -```objectivec +```objectivec // GOOD: int32_t scalar1 = proto.intValue; @@ -611,7 +688,7 @@ NSUInteger numberOfObjects = array.count; CGFloat offset = view.bounds.origin.x; ``` -```objectivec +```objectivec // AVOID: NSInteger scalar2 = proto.longValue; // AVOID. @@ -620,7 +697,45 @@ 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 + + +#### Floating Point Constants + +When defining `CGFloat` constants, please keep in mind the following. + +Previously for projects targeting 32-bit platforms, using `float` literals +(numbers with the `f` suffix) could be necessary to avoid type-conversion +warnings. + +Since all Google iOS projects are now targeting only 64-bit runtime, `CGFloat` +constants may omit the suffix (use `double` values). However, teams may choose +to continue using `float` numbers for legacy code consistency, until they +eventually migrate to `double` values everywhere. Avoid a mixture of `float` +and `double` values in the same code. + +```objectivec +// GOOD: + +// Good since CGFloat is double +static const CGFloat kHorizontalMargin = 8.0; +static const CGFloat kVerticalMargin = 12.0; + +// This is OK as long as all values for CGFloat constants in your project are float +static const CGFloat kHorizontalMargin = 8.0f; +static const CGFloat kVerticalMargin = 12.0f; +``` + +```objectivec +// AVOID: + +// Avoid a mixture of float and double constants +static const CGFloat kHorizontalMargin = 8.0f; +static const CGFloat kVerticalMargin = 12.0; +``` + + + +## 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 @@ -635,13 +750,19 @@ 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 +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. + +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 @@ -649,7 +770,9 @@ the author line since revision history already provides a more detailed and accurate record of authorship. -### Declaration Comments + + +### 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. @@ -657,7 +780,8 @@ 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 + +```objectivec // GOOD: /** @@ -678,8 +802,10 @@ categories, protocol declarations, and enums. @end ``` -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; +[Doxygen](https://doxygen.nl)-style comments are encouraged for interfaces as +they are parsed by Xcode +to display formatted documentation. There is a wide variety of +[Doxygen commands](https://www.doxygen.nl/manual/commands.html); use them consistently within a project. If you have already described an interface in detail in the comments at the top @@ -706,11 +832,18 @@ 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 +Declaration comments may be omitted on test case classes and test methods +if comments would communicate no additional information beyond the method's +name. Utility methods in tests or test-specific classes (such as helpers) should +be commented. + + + +### Implementation Comments Provide comments explaining tricky, subtle, or complicated sections of code. -```objectivec +```objectivec // GOOD: // Set the property to nil before invoking the completion handler to @@ -728,27 +861,30 @@ 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 +```objectivec // GOOD: [self doSomethingWithALongName]; // Two spaces before the comment. [self doSomethingShort]; // More spacing to align the comment. ``` -### Disambiguating Symbols + + + +### 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`. +command, such as [`@c`](https://www.doxygen.nl/manual/commands.html#cmdc). 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 +```objectivec // GOOD: // Sometimes `count` will be less than zero. @@ -756,7 +892,7 @@ the sentence read like it was poorly constructed. A common example is the symbol or when quoting something which already contains quotes -```objectivec +```objectivec // GOOD: // Remember to call `StringWithoutSpaces("foo bar baz")` @@ -764,7 +900,7 @@ or when quoting something which already contains quotes Backticks or vertical bars are not needed when a symbol is self-apparent. -```objectivec +```objectivec // GOOD: // This class serves as a delegate to GTMDepthCharge. @@ -772,18 +908,22 @@ Backticks or vertical bars are not needed when a symbol is self-apparent. Doxygen formatting is also suitable for identifying symbols. -```objectivec +```objectivec // GOOD: /** @param maximum The highest value for @c count. */ ``` -### Object Ownership + + +### 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 + + +#### 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 @@ -800,7 +940,7 @@ even when building for automatic reference counting. Examples of strong and weak declarations: -```objectivec +```objectivec // GOOD: @interface MyDelegate : NSObject @@ -824,16 +964,22 @@ Examples of strong and weak declarations: @end ``` -#### Automatic Reference Counting + + +#### 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 +## C Language Features -Avoid macros, especially where `const` variables, enums, XCode snippets, or C + + +### 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 @@ -849,7 +995,7 @@ 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 +```objectivec // GOOD: #define GTM_EXPERIMENTAL_BUILD ... // GOOD @@ -861,7 +1007,7 @@ practices. Do not define macros that appear to be C or Objective-C keywords. #define GTMAssertGreaterThan(X, Y) ... // GOOD, function style. ``` -```objectivec +```objectivec // AVOID: #define kIsExperimentalBuild ... // AVOID @@ -880,7 +1026,7 @@ 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 +```objectivec // AVOID: #define ARRAY_ADDER(CLASS) \ @@ -897,7 +1043,9 @@ 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 Nonstandard extensions to C/Objective-C may not be used unless otherwise specified. @@ -905,48 +1053,121 @@ 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 })`). -`__attribute__` is an approved exception, as it is used in Objective-C API -specifications. +#### The `__typeof__` Keyword -The binary form of the conditional operator, `A ?: B`, is an approved exception. +The `__typeof__` keyword is allowed in cases where the type doesn't aid in +clarity for the reader. The `__typeof__` keyword is encouraged over other +similar keywords (e.g., the `typeof` keyword) as it is supported in all language +variants. -## Cocoa and Objective-C Features +```objectivec +// GOOD: -### Identify Designated Initializer + __weak __typeof__(self) weakSelf = self; +``` -Clearly identify your designated initializer. +```objectivec +// AVOID: -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`. + __typeof__(data) copiedData = [data copy]; // AVOID. + __weak typeof(self) weakSelf = self; // AVOID. +``` -### Override Designated Initializer +#### The `__auto_type` Keyword and Type Deduction -When writing a subclass that requires an `init...` method, make sure you -override the designated initializer of the superclass. +Type deduction using the `__auto_type` keyword is allowed only for local +variables of block and function pointer types. Avoid type deduction if a typedef +already exists for the block or pointer type. -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. +```objectivec +// GOOD: -### Overridden NSObject Method Placement +__auto_type block = ^(NSString *arg1, int arg2) { ... }; +__auto_type functionPointer = &MyFunction; + +typedef void(^SignInCallback)(Identity *, NSError *); +SignInCallback signInCallback = ^(Identity *identity, NSError *error) { ... }; +``` + +```objectivec +// AVOID: + +__auto_type button = [self createButtonForInfo:info]; +__auto_type viewController = [[MyCustomViewControllerClass alloc] initWith...]; + +typedef void(^SignInCallback)(Identity *, NSError *); +__auto_type signInCallback = ^(Identity *identity, NSError *error) { ... }; +``` + +#### Approved Nonstandard Extensions + +* The `__attribute__` keyword is approved as it is used in Apple API + declarations. +* The binary form of the conditional operator, `A ?: B`, is approved. + + + +## Cocoa and Objective-C Features + + + +### Identify Designated Initializers + +Clearly identify your designated initializer(s). + +It is important for subclassing that a class clearly identify its designated +initializers. This allows a subclass to override a subset of initializers to +initialize subclass state or invoke a new designated initializer provided by the +subclass. Clearly identified designated initializers also make tracing through +and debugging initialization code easier. + +Prefer identifying designated initializers by annotating them with designated +initializer attributes, e.g., `NS_DESIGNATED_INITIALIZER`. Declare designated +initializers in comments when designated initializer attributes are not +available. Prefer a single designated initializer unless there is a compelling +reason or requirement for multiple designated initializers. + +Support initializers inherited from superclasses by +[overriding superclass designated initializers](#Override_Designated_Initializer) +to ensure that all inherited initializers are directed through subclass +designated initializers. When there is a compelling reason or requirement that +an inherited initializer should not be supported, the initializer may be +annotated with availability attributes (e.g., `NS_UNAVAILABLE`) to discourage +usage; however, note that availability attributes alone do not completely +protect against invalid initialization. + + + +### Override Designated Initializers + +When writing a subclass that requires a new designated initializer, make sure +you override any designated initializers of the superclass. + +When declaring designated initializers on a class, remember that any +initializers that were considered designated initializers on the superclass +become convenience initializers of the subclass unless declared otherwise. +Failure to override superclass designated initializers can result in bugs due to +invalid initialization using superclass initializers. To avoid invalid +initialization, ensure convenience initializers call through to a designated +initializer. + + + +### 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`. +including those `init...` methods that are not `NSObject` overrides, 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 + + +### Initialization Don't initialize instance variables to `0` or `nil` in the `init` method; doing so is redundant. @@ -956,13 +1177,15 @@ to](https://developer.apple.com/library/mac/documentation/General/Conceptual/Coc `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 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 +```objectivec // GOOD: @interface MyClass : NSObject { @@ -972,13 +1195,17 @@ should be marked `@protected` or `@private`. @end ``` -### Do Not Use +new + + +### Do Not Use +new Do not invoke the `NSObject` class method `new`, nor override it in a subclass. `+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 + + +### 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. @@ -995,16 +1222,21 @@ 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 and #include `#import` Objective-C and Objective-C++ headers, and `#include` C/C++ headers. 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 + + +### 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 @@ -1014,13 +1246,12 @@ 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. - -Within each group the includes should be ordered alphabetically. +Separate each non-empty group of includes with one blank line. Within each group +the includes should be ordered alphabetically. Import headers using their path relative to the project's source directory. -```objectivec +```objectivec // GOOD: #import "ProjectX/BazViewController.h" @@ -1032,13 +1263,16 @@ Import headers using their path relative to the project's source directory. #include "base/basictypes.h" #include "base/integral_types.h" +#import "base/mac/FOOComplexNumberSupport" #include "util/math/mathutil.h" #import "ProjectX/BazModel.h" #import "Shared/Util/Foo.h" ``` -### Use Umbrella Headers for System Frameworks + + +### Use Umbrella Headers for System Frameworks Import umbrella headers for system frameworks and system libraries rather than include individual files. @@ -1049,14 +1283,14 @@ 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 +```objectivec // GOOD: @import UIKit; // GOOD. #import // GOOD. ``` -```objectivec +```objectivec // AVOID: #import // AVOID. @@ -1066,7 +1300,8 @@ pre-compiled and can be loaded much more quickly. In addition, remember to use ### Avoid Messaging the Current Object Within Initializers and `-dealloc` -Code in initializers and `-dealloc` should avoid invoking instance methods. +Code in initializers and `-dealloc` should avoid invoking instance methods when +possible. Superclass initialization completes before subclass initialization. Until all classes have had a chance to initialize their instance state any method @@ -1080,7 +1315,7 @@ One case where this is less obvious is property accessors. These can be overridden just like any other selector. Whenever practical, directly assign to and release ivars in initializers and `-dealloc`, rather than rely on accessors. -```objectivec +```objectivec // GOOD: - (instancetype)init { @@ -1099,7 +1334,7 @@ Beware of factoring common initialization code into helper methods: - When editing a helper method, it may not be obvious that the code is being run from an initializer. -```objectivec +```objectivec // AVOID: - (instancetype)init { @@ -1112,7 +1347,7 @@ Beware of factoring common initialization code into helper methods: } ``` -```objectivec +```objectivec // GOOD: - (void)dealloc { @@ -1120,7 +1355,7 @@ Beware of factoring common initialization code into helper methods: } ``` -```objectivec +```objectivec // AVOID: - (void)dealloc { @@ -1128,30 +1363,217 @@ Beware of factoring common initialization code into helper methods: } ``` -### Setters copy NSStrings +There are common cases where a class may need to use properties and methods +provided by a superclass during initialization. This commonly occurs for classes +derived from UIKit and AppKit base classes, among other base classes. Use your +judgement and knowledge of common practice when deciding whether to make an +exception to this rule. -Setters taking an `NSString` should always copy the string it accepts. This is -often also appropriate for collections like `NSArray` and `NSDictionary`. +### Avoid redundant property access -Never just retain the string, as it may be a `NSMutableString`. This avoids the -caller changing it under you without your knowledge. +Code should avoid redundant property access. Prefer to assign a property value +to a local variable when the property value is not expected to change and needs +to be used multiple times. -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 +```objc // GOOD: -@property(nonatomic, copy) NSString *name; +UIView *view = self.view; +UIScrollView *scrollView = self.scrollView; +[scrollView.leadingAnchor constraintEqualToAnchor:view.leadingAnchor].active = YES; +[scrollView.trailingAnchor constraintEqualToAnchor:view.trailingAnchor].active = YES; +``` -- (void)setZigfoos:(NSArray *)zigfoos { - // Ensure that we're holding an immutable collection. - _zigfoos = [zigfoos copy]; +```objc +// AVOID: + +[self.scrollView.loadingAnchor constraintEqualToAnchor:self.view.loadingAnchor].active = YES; +[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES; +``` + +When repeatedly referencing chained property invocations, prefer to capture the +repeated expression in a local variable: + +```objc +// AVOID: + +foo.bar.baz.field1 = 10; +foo.bar.baz.field2 = @"Hello"; +foo.bar.baz.field3 = 2.71828183; +``` + +```objc +// GOOD: + +Baz *baz = foo.bar.baz; +baz.field1 = 10; +baz.field2 = @"Hello"; +baz.field3 = 2.71828183; +``` + +Redundantly accessing the same properties results in multiple message dispatches +to fetch the same value, and under ARC requires retains and releases of any +returned objects; the compiler cannot optimize away these extra operations, +leading to slower execution and substantial increases in binary size. + + + + +### Mutables, Copies and Ownership + +For [Foundation and other hierarchies containing both immutable and mutable +subclasses](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html) +a mutable subclass may be substituted for an immutable so long as the +immutable's contract is honored. + +The most common example of this sort of substitution are ownership transfers, +particularly for return values. In these cases an additional copy is not +necessary and returning the mutable subclass is more efficient. +[Callers are expected to treat return values as their declared type](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html#//apple_ref/doc/uid/TP40010810-CH5-SW67), +and thus the return value will be treated as an immutable going forward. + +```objectivec +// GOOD: + +- (NSArray *)listOfThings { + NSMutableArray *generatedList = [NSMutableArray array]; + for (NSInteger i = 0; i < _someLimit; i++) { + [generatedList addObject:[self thingForIndex:i]]; + } + // Copy not necessary, ownership of generatedList is transferred. + return generatedList; } ``` -### Use Lightweight Generics to Document Contained Types +This rule also applies to classes where only a mutable variant exists so long as +the ownership transfer is clear. Protos are a common example. + +```objectivec +// GOOD: + +- (SomeProtoMessage *)someMessageForValue:(BOOL)value { + SomeProtoMessage *message = [SomeProtoMessage message]; + message.someValue = value; + return message; +} +``` + +It is not necessary to create a local immutable copy of a mutable type to match +the method signature of a method being called so long as the mutable argument +will not change for the duration of the method call. Called methods are expected +to treat arguments as the declared type, and take +[defensive copies](#Defensive_Copies) +([referred to by Apple as "snapshots"](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html#//apple_ref/doc/uid/TP40010810-CH5-SW68)) +if they intend to retain those arguments beyond the duration of the call. + +```objectivec +// AVOID: + +NSMutableArray *updatedThings = [NSMutableArray array]; +[updatedThings addObject:newThing]; +[_otherManager updateWithCurrentThings:[updatedThings copy]]; // AVOID +``` + + + + +### Copy Potentially Mutable Objects + +Code receiving and retaining collections or other types with +[mutable variants](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html) +should consider that the passed object may be mutable, and thus an immutable or +mutable copy should be retained instead of the original object. In particular, +initializers and setters +[should copy instead of retaining objects whose types have mutable variants](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html#//apple_ref/doc/uid/TP40010810-CH5-SW68). + +Synthesized accessors should use the `copy` keyword to ensure the generated code +matches these expectations. + +NOTE: [The `copy` property keyword only affects the synthesized setter and has +no effect on +getters](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW27). +Since property keywords have no effect on direct ivar access custom accessors +must implement the same copy semantics. + +```objectivec +// GOOD: + +@property(nonatomic, copy) NSString *name; +@property(nonatomic, copy) NSSet *filters; + +- (instancetype)initWithName:(NSString *)name + filters:(NSSet *)filters { + self = [super init]; + if (self) { + _name = [name copy]; + _filters = [filters copy]; + } + return self; +} + +- (void)setFilters:(NSSet *)filters { + // Ensure that we retain an immutable collection. + _filters = [filters copy]; +} +``` + +Similarly, getters must return types that match the contract expectations of the +immutable types they return. + +```objectivec +// GOOD: + + +@implementation Foo { + NSMutableArray *_currentContent; +} + +- (NSArray *)currentContent { + return [_currentContent copy]; +} + +``` + +All Objective-C protos are mutable and typically should be copied rather than +retained +[except in clear cases of ownership transfer](#Mutables_Copies_Ownership). + +```objectivec +// GOOD: + +- (void)setFooMessage:(FooMessage *)fooMessage { + // Copy proto to ensure no other retainer can mutate our value. + _fooMessage = [fooMessage copy]; +} + +- (FooMessage *)fooMessage { + // Copy proto to return so that caller cannot mutate our value. + return [_fooMessage copy]; +} +``` + +Asynchronous code should copy potentially mutable objects prior to dispatch. +Objects captured by blocks are retained but not copied. + +```objectivec +// GOOD: + +- (void)doSomethingWithThings:(NSArray *)things { + NSArray *thingsToWorkOn = [things copy]; + dispatch_async(_workQueue, ^{ + for (id thing in thingsToWorkOn) { + ... + } + }); +} +``` + +NOTE: It is unnecessary to copy objects that do not have mutable variants, e.g. +`NSURL`, `NSNumber`, `NSDate`, `UIColor`, etc. + + + +### 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. @@ -1159,7 +1581,7 @@ 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 +```objectivec // GOOD: @property(nonatomic, copy) NSArray *locations; @@ -1171,7 +1593,7 @@ NSMutableArray *mutableLocations = [otherObject.locations mutableC If the fully-annotated types become complex, consider using a typedef to preserve readability. -```objectivec +```objectivec // GOOD: typedef NSSet *> TimeZoneMappingSet; @@ -1182,13 +1604,15 @@ 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 heterogeneous using id. -```objectivec +```objectivec // GOOD: @property(nonatomic, copy) NSArray *unknowns; ``` -### Avoid Throwing Exceptions + + +### Avoid Throwing Exceptions Don't `@throw` Objective-C exceptions, but you should be prepared to catch them from third-party or OS calls. @@ -1202,7 +1626,9 @@ 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 + + +### `nil` Checks Avoid `nil` pointer checks that exist only to prevent sending messages to `nil`. Sending a message to `nil` [reliably @@ -1210,7 +1636,7 @@ returns](http://www.sealiesoftware.com/blog/archive/2012/2/29/objc_explain_retur `nil` as a pointer, zero as an integer or floating-point value, structs initialized to `0`, and `_Complex` values equal to `{0, 0}`. -```objectivec +```objectivec // AVOID: if (dataSource) { // AVOID. @@ -1218,7 +1644,7 @@ if (dataSource) { // AVOID. } ``` -```objectivec +```objectivec // GOOD: [dataSource moveItemAtIndex:1 toIndex:0]; // GOOD. @@ -1242,20 +1668,20 @@ 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 +```objectivec // GOOD: /** A class representing an owned book. */ @interface GTMBook : NSObject /** The title of the book. */ -@property(readonly, copy, nonnull) NSString *title; +@property(nonatomic, readonly, copy, nonnull) NSString *title; /** The author of the book, if one exists. */ -@property(readonly, copy, nullable) NSString *author; +@property(nonatomic, readonly, copy, nullable) NSString *author; /** The owner of the book. Setting nil resets to the default owner. */ -@property(copy, null_resettable) NSString *owner; +@property(nonatomic, copy, null_resettable) NSString *owner; /** Initializes a book with a title and an optional author. */ - (nonnull instancetype)initWithTitle:(nonnull NSString *)title @@ -1271,38 +1697,49 @@ e.g., `nonnull` and `nullable`. NSArray *_Nullable GTMLoadBooksFromFile(NSString *_Nonnull path); ``` -```objectivec +```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. +Do not assume that a pointer is not null based on a nonnull qualifier, because +the compiler only checks a subset of such cases, and does not guarantee that the +pointer is not null. Avoid intentionally violating nullability semantics +of function, method, and property declarations. -### BOOL Pitfalls + + +### BOOL Pitfalls + + +#### BOOL Expressions and Conversions Be careful when converting general integral values to `BOOL`. Avoid comparing -directly with `YES`. +directly with `YES` or comparing multiple `BOOL` values with comparison +operators. -`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`. +`BOOL` on some Apple platforms (notably Intel macOS, watchOS, and 32-bit iOS) +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. +or the result of a bitwise logic operation to a `BOOL`. These operations can +depend on the value of the last byte of the integer value and result in an +unexpected `NO` value. Operations with NS_OPTIONS values and flag masking are +especially common errors. + +When converting a general integral value to a `BOOL`, use conditional 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. +conditional operator. -```objectivec +```objectivec // AVOID: - (BOOL)isBold { @@ -1311,9 +1748,12 @@ ternary operator. - (BOOL)isValid { return [self stringValue]; // AVOID. } +- (BOOL)isLongEnough { + return (BOOL)([self stringValue].count); // AVOID. +} ``` -```objectivec +```objectivec // GOOD: - (BOOL)isBold { @@ -1322,16 +1762,19 @@ ternary operator. - (BOOL)isValid { return [self stringValue] != nil; } +- (BOOL)isLongEnough { + return [self stringValue].count > 0; +} - (BOOL)isEnabled { return [self isValid] && [self isBold]; } ``` -Also, don't directly compare `BOOL` variables directly with `YES`. Not only is +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 +```objectivec // AVOID: BOOL great = [foo isGreat]; @@ -1340,7 +1783,7 @@ if (great == YES) { // AVOID. } ``` -```objectivec +```objectivec // GOOD: BOOL great = [foo isGreat]; @@ -1349,21 +1792,93 @@ if (great) { // GOOD. } ``` -### Interfaces Without Instance Variables +Don't directly compare `BOOL` values using comparison operators. `BOOL` +values that are true may not be equal. Use logical operators in place +of bitwise comparisons of `BOOL` values. -Omit the empty set of braces on interfaces that do not declare any instance -variables. +```objectivec +// AVOID: -```objectivec +if (oldBOOLValue != newBOOLValue) { // AVOID. + // ... code that should only run when the value changes. +} +``` + +```objectivec +// GOOD: + +if ((!oldBoolValue && newBoolValue) || (oldBoolValue && !newBoolValue)) { // GOOD. + // ... code that should only run when the value changes. +} + +// GOOD, the results of logical operators on BOOLs are safe to compare. +if (!oldBoolValue != !newBoolValue) { + // ... code that should only run when the value changes. +} +``` + +#### BOOL Literals + +The [BOOL NSNumber literals](https://clang.llvm.org/docs/ObjectiveCLiterals.html#nsnumber-literals) +are `@YES` and `@NO` which are equivalent to `[NSNumber numberWithBool:...]`. + +Avoid using [boxed expressions](https://clang.llvm.org/docs/ObjectiveCLiterals.html#boxed-expressions) +to create BOOL values, including simple expressions like `@(YES)`. +Boxed expressions suffer from [the same pitfalls as other BOOL expressions] +(#BOOL_Expressions_Conversions) as boxing general integral values can +produce true or false `NSNumbers` that are not equal to `@YES` and `@NO`. + +When converting a general integral value to a BOOL literal, use conditional +operators to convert to `@YES` or `@NO`. Do not embed a conditional operator +inside a boxed expression as this is equivalent to boxing general integral +values even when the result of the operation is a BOOL. + +```objectivec +// AVOID: + +[_boolArray addValue:@(YES)]; // AVOID boxing even in simple cases. +NSNumber *isBold = @(self.fontTraits & NSFontBoldTrait); // AVOID. +NSNumber *hasContent = @([self stringValue].length); // AVOID. +NSNumber *isValid = @([self stringValue]); // AVOID. +NSNumber *isStringNotNil = @([self stringValue] ? YES : NO); // AVOID. +``` + +```objectivec +// GOOD: + +[_boolArray addValue:@YES]; // GOOD. +NSNumber *isBold = self.fontTraits & NSFontBoldTrait ? @YES : @NO; // GOOD. +NSNumber *hasContent = [self stringValue].length ? @YES : @NO; // GOOD. +NSNumber *isValid = [self stringValue] ? @YES : @NO; // GOOD. +NSNumber *isStringNotNil = [self stringValue] ? @YES : @NO; // GOOD. +``` + + + + +### Containers Without Instance Variables + +Omit the empty set of braces on interfaces, class extensions, and +implementations without any instance variable declarations. + +```objectivec // GOOD: @interface MyClass : NSObject // Does a lot of stuff. - (void)fooBarBam; @end + +@interface MyClass () +- (void)classExtensionMethod; +@end + +@implementation MyClass +// Actual implementation. +@end ``` -```objectivec +```objectivec // AVOID: @interface MyClass : NSObject { @@ -1371,11 +1886,25 @@ variables. // Does a lot of stuff. - (void)fooBarBam; @end + +@interface MyClass () { +} +- (void)classExtensionMethod; +@end + +@implementation MyClass { +} +// Actual implementation. +@end ``` -## Cocoa Patterns + -### Delegate Pattern +## Cocoa Patterns + + + +### Delegate Pattern Delegates, target objects, and block pointers should not be retained when doing so would create a retain cycle. @@ -1392,9 +1921,13 @@ 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 +## 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 @@ -1407,7 +1940,7 @@ 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++ +```objectivec++ // GOOD: // file: cross_platform_header.h @@ -1456,9 +1989,13 @@ 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 +## 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. @@ -1466,21 +2003,22 @@ 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 + + +### 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 +### 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. +One space should be used between the `-` or `+` and the return type. In general, +there should be no spacing in the parameter list except between parameters. Methods should look like this: -```objectivec +```objectivec // GOOD: - (void)doSomethingWithString:(NSString *)theString { @@ -1497,9 +2035,11 @@ 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. +first. If a parameter declared after the `:` in a method declaration or +definition would cause the line limit to be exceeded, wrap the content to the +next line indented by at least four spaces. -```objectivec +```objectivec // GOOD: - (void)doSomethingWithFoo:(GTMFoo *)theFoo @@ -1520,6 +2060,11 @@ first. - (void)presentWithAdaptivePresentationControllerDelegate: (id)delegate; + +- (void)updateContentHeaderViewForExpansionToContentOffset:(CGPoint)contentOffset + withController: + (GTMCollectionExpansionController *)controller; + ``` ### Function Declarations and Definitions @@ -1529,10 +2074,10 @@ 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 +```objectivec // GOOD: -NSString *GTMVersionString(int majorVersion, minorVersion) { +NSString *GTMVersionString(int majorVersion, int minorVersion) { ... } @@ -1563,12 +2108,14 @@ conditions: * Function scopes should be indented 2 spaces. * Wrapped parameters should have a 4 space indent. -### Conditionals + + +### Conditionals Include a space after `if`, `while`, `for`, and `switch`, and around comparison operators. -```objectivec +```objectivec // GOOD: for (int i = 0; i < 5; ++i) { @@ -1580,7 +2127,7 @@ while (test) {}; Braces may be omitted when a loop body or conditional statement fits on a single line. -```objectivec +```objectivec // GOOD: if (hasSillyName) LaughOutLoud(); @@ -1590,7 +2137,7 @@ for (int i = 0; i < 10; i++) { } ``` -```objectivec +```objectivec // AVOID: if (hasSillyName) @@ -1602,7 +2149,7 @@ for (int i = 0; i < 10; i++) If an `if` clause has an `else` clause, both clauses should use braces. -```objectivec +```objectivec // GOOD: if (hasBaz) { @@ -1612,7 +2159,7 @@ if (hasBaz) { } ``` -```objectivec +```objectivec // AVOID: if (hasBaz) foo(); @@ -1626,7 +2173,7 @@ if (hasBaz) { 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 +```objectivec // GOOD: switch (i) { @@ -1647,12 +2194,14 @@ switch (i) { } ``` -### Expressions + + +### Expressions Use a space around binary operators and assignments. Omit a space for a unary operator. Do not add spaces inside parentheses. -```objectivec +```objectivec // GOOD: x = 0; @@ -1662,20 +2211,22 @@ v = -y * (x + z); Factors in an expression may omit spaces. -```objectivec +```objectivec // GOOD: v = w*x + y/z; ``` -### Method Invocations + + +### 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 +```objectivec // GOOD: [myObject doFooWith:arg1 name:arg2 error:arg3]; @@ -1683,7 +2234,7 @@ in a given source file. Invocations should have all arguments on one line: or have one argument per line, with colons aligned: -```objectivec +```objectivec // GOOD: [myObject doFooWith:arg1 @@ -1693,7 +2244,7 @@ or have one argument per line, with colons aligned: Don't use any of these styles: -```objectivec +```objectivec // AVOID: [myObject doFooWith:arg1 name:arg2 // some lines with >1 arg @@ -1711,7 +2262,7 @@ 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 +```objectivec // GOOD: [myObj short:arg1 @@ -1723,7 +2274,9 @@ alignment: Invocations containing multiple inlined blocks may have their parameter names left-aligned at a four space indent. -### Function Calls + + +### 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. @@ -1731,7 +2284,7 @@ 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 +```objectivec // GOOD: CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, objects, numberOfObjects, @@ -1752,14 +2305,16 @@ TransformImage(image, Use local variables with descriptive names to shorten function calls and reduce nesting of calls. -```objectivec +```objectivec // GOOD: double scoreHeuristic = scores[x] * y + bases[x]; UpdateTally(scoreHeuristic, x, y, z); ``` -### Exceptions + + +### 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 @@ -1768,7 +2323,7 @@ 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 +```objectivec // GOOD: @try { @@ -1780,7 +2335,9 @@ exceptions. } ``` -### Function Length + + +### Function Length Prefer small and focused functions. @@ -1796,7 +2353,9 @@ and modify your code. When updating legacy code, consider also breaking long functions into smaller and more manageable pieces. -### Vertical Whitespace + + +### Vertical Whitespace Use vertical whitespace sparingly. @@ -1806,9 +2365,13 @@ 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 +## 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