Skip to content

Objective C Style Guide

Joel Fischer edited this page Mar 25, 2015 · 8 revisions

These guidelines build on the Apple Coding Guidelines for Cocoa.

Partially based on the Github, New York Times, and Dropbox style guides.

Whitespace

  • Spaces not tabs
  • End files with a newline
  • Use whitespace to divide code into chunks
  • No trailing whitespace on lines

Comments

  • Block comments should only exist for generated documentation. Inline comments should be used to explain why a particular piece of code exists, not what it does, which ought to be obvious if well written.

Pragma

  • #pragma mark methods into logical clusters. Use #pragma mark - for major functionality groups, #pragma mark for minor functionality groups.

TODOs

  • Label TODO and FIXME comments with a name and date, follow the formatting shown below.
  • All FIXME comments must be fixed or deleted before a release.
// TODO: (Joel F.)[2015-03-22] Make sure we do the thing!

Imports

  • Start with local imports (.m files import their own header first), then import global headers after.
  • Import alphabetically.

Declarations

Properties

  • Use strong properties only if exposing a mutable object, or one that does not conform to <NSCopying>. Prefer copy in other instances.
  • Properties should be declared nonatomic by default unless there is a very good reason to use atomic, which will be rare.

Instance Variables

  • If a property is mutable as an implementation detail, and does not need to be exposed as mutable, expose an immutable type for that property instead, and declare the ivar as mutable.
  • Except for the above rule, always create properties instead of iVars. Private properties should be generated in an interface extension.
  • iVars should be prefixed with an underscore, like implicitly synthesized ones.
  • Access properties by iVar only if in -init, -dealloc, or a custom accessor.

Local Variables

  • Always initialize local variables, they will not be automatically initialized to nil or 0.

Methods

  • If a private method can be a class method instead of an instance method, it should be a class method.
  • Private methods should be prefixed with the project prefix sdl.
+ (void)sdl_privateClassMethod {}
  • Protected methods should be declared in a class extension that subclasses implement and other classes do not.

Constants

  • Prefer constants to inline string literals and numbers to more easily change them if necessary. Constants should be declared as static constants that are exported if public, and not #define.

Expressions

  • Access properties and structs by dot-syntax, everything else (including idempotent methods) via bracket syntax.

Literals

  • Binary operands should be separated with a space, unary and casts with no space.
for (int i = 0; i < 10; i++) {}
void *thing = &thing;
SuperThing newThing = (SuperThing)subThing;
  • NSString, NSDictionary, NSArray, and NSNumber literals should be used whenever possible. When turning a non-NSNumber number variable into an NSNumber, box the number with @().
NSString *string = @"string";
NSArray *array = @[ @1, @2, @3 ];
NSDictionary *dict = @{ @"key": value };
NSNumber *number = @42;
  • Complex dictionary and array literals should be split across multiple lines.
NSDictionary *complexDict = @{
	@"key1": value1,
	@"key2": value2,
	@"key3": value3
};

Enums

  • To declare enumerations, use NS_ENUM. To declare options (bitmasks) use NS_OPTIONS.
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

Switch

  • For case blocks that are one line, you may omit braces. This will usually only happen if break is the only statement.
  • For case blocks that contain more than one line, wrap the lines in braces.
  • When falling through a case statement, explicitly mark it with the comment //fallthrough
  • If possible, default should be an assertion.
switch(someEnum) {
	case someEnumValue: {
		// Do many things
	} break;
	case someEnumValue2: // Fallthrough
	case someEnumValue3: {
		// Do a few more things
	} break;
	default: NSAssert("Unknown enum value %@", @(someEnum));
}

Conditionals

  • Conditionals should always contain braces.
  • Comparisons should always be explicit except for BOOL values. BOOL values are actually a signed char, and explicit comparisons can lead to incorrect results in certain cases, such as setting a BOOL to the result of an array's length.
  • Ternary operators should only be used when they improve clarity in assignments and arguments. They should be wrapped in parenthesis.
  • Coalescing ternary operators should not use parenthesis.
if (someObject != nil) {
	// Do the thing
} else if (someBool) {
	// Do the other thing
} else {
	// Do the last thing
}

NSString *someString = (isTrue ? @"YES" : @"NO");
NSString *someOtherString = optionalValue ?: defaultValue;

Exceptions and Errors

  • Never use exceptions for flow control, only for programmer error.
  • Use NSError to indicate all other fault types. To indicate that a method may error, receive an NSError ** parameter.
  • Make sure to test for nullability on the error argument before setting it.
Clone this wiki locally