Skip to content

sprucehealth/objective-c-conventions

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

87 Commits
 
 

Repository files navigation

These guidelines build on Apple's existing Coding Guidelines for Cocoa. Unless explicitly contradicted below, assume that all of Apple's guidelines apply as well. Bold indicates a deviation from GitHub's conventions. Strikethrough indicates removal of a GitHub rule.

Whitespace

  • Spaces, not tabs. 4 space width.
  • End files with a newline.
  • Make liberal use of vertical whitespace to divide code into logical chunks.

Documentation and Organization

  • All method declarations should be documented.
  • Comments should be hard-wrapped at 80 characters.
  • Any public documentation should use AppleDoc format
  • Document whether object parameters allow nil as a value when appropriate.
  • Use #pragma marks to categorize methods into functional groupings and protocol implementations, following this general structure:
#pragma mark - Lifecycle

+ (id)objectWithThing:(id)thing {}
- (id)init {}

#pragma mark - Properties

@dynamic someProperty;

- (void)setCustomProperty:(id)value {}

#pragma mark - Drawing

- (void)drawRect:(CGRect) {}

#pragma mark - Another functional grouping

#pragma mark - GHSuperclass

- (void)someOverriddenMethod {}

#pragma mark - NSCopying

- (id)copyWithZone:(NSZone *)zone {}

#pragma mark - NSObject

- (NSString *)description {}

Declarations

  • Never declare an ivar unless you need to change its type from its declared property.
  • Don’t use line breaks in method declarations.
  • Prefer exposing an immutable type for a property if it being mutable is an implementation detail. This is a valid reason to declare an ivar for a property.
  • Always declare memory-management semantics even except on readonly properties that will be generated dynamically. However, readonly properties that will be stored internally should have memory-management semantics declared. This distinguishes generated properties from properties that just are immutable.
  • Declare properties readonly if they are only set once in -init.
  • Declare properties copy if they return immutable objects and aren't ever mutated in the implementation.
  • Don't use @synthesize unless the compiler requires it. Note that optional properties in protocols must be explicitly synthesized in order to exist.
  • Instance variables should be prefixed with an underscore (just like when implicitly synthesized).
  • Don't put a space between an object type and the protocol it conforms to.
@property (attributes) id<Protocol> object;
@property (nonatomic, strong) NSObject<Protocol> *object;
  • C function declarations should have no space before the opening parenthesis, and should be namespaced just like a class.
void GHAwesomeFunction(BOOL hasSomeArgs);
  • Constructors should generally return instancetype rather than id.
  • Prefer C99 struct initialiser syntax to helper functions (such as CGRectMake()).
  CGRect rect = { 
      .origin.x = 3.0,
      .origin.y = 12.0, 
      .size.width = 15.0, 
      .size.height = 80.0,
  };

Expressions

  • Don't access an ivar unless you're in -init, -dealloc or a custom accessor.
  • Use dot-syntax when invoking idempotent methods, including setters and class methods (like NSFileManager.defaultManager).
  • Use object literals, boxed expressions, and subscripting over the older, grosser alternatives.
  • Comparisons should be explicit for everything except BOOLs and pointer comparisons to nil. (i.e. don't do if (index) with an NSInteger)
  • Prefer positive comparisons to negative.
  • obj == nil is prefered over !obj
  • Don't nest ternary operators.
  • Long form ternary operators should be wrapped in parentheses and only used for assignment and arguments.
Blah *a = (stuff == thing ? foo : bar);
  • Short form, nil coalescing ternary operators should avoid parentheses.
Blah *b = thingThatCouldBeNil ?: defaultValue;
  • Separate binary operands with a single space, but unary operands and casts with none:
void *ptr = &value + 10 * 3;
NewType a = (NewType)b;

for (int i = 0; i < 10; i++) {
    doCoolThings();
}

Control Structures

  • Always surround if bodies with curly braces if there is an else. Single-line if bodies without an else should be on the same line as the if.
  • All curly braces should begin on the same line as their associated statement. They should end on a new line.
  • Put a single space after keywords and before their parentheses.
  • No spaces between parentheses and their contents.
if (shitIsBad) return;

if (something == nil) {
	// do stuff
} else {
	// do other stuff
}

Exceptions and Error Handling

  • Don't use exceptions for flow control.
  • Use exceptions only to indicate programmer error.
  • To indicate errors, use an NSError ** argument, or failure block. or send an error on a ReactiveCocoa signal.

Blocks

  • Blocks should have a space between their return type and name.
  • Block definitions should omit their return type when possible.
  • Block definitions should omit their arguments if they are void.
  • Parameters in block types should be named unless the block is initialized immediately.
void (^blockName1)(void) = ^{
    // do some things
};

id (^blockName2)(id) = ^ id (id args) {
    // do some things
};

Literals

  • Avoid making numbers a specific type unless necessary (for example, prefer 5 to 5.0, and 5.3 to 5.3f).
  • The contents of array and dictionary literals should have a space on both sides.
  • Dictionary literals should have no space between the key and the colon, and a single space between the colon and value.
NSArray *theShit = @[ @1, @2, @3 ];

NSDictionary *keyedShit = @{ GHDidCreateStyleGuide : @YES };
  • Longer or more complex literals should be split over multiple lines (optionally with a terminating comma):
NSArray *theShit = @[
    @"Got some long string objects in here.",
    [AndSomeModelObjects too],
    @"Moar strings."
];

NSDictionary *keyedShit = @{
    @"this.key": @"corresponds to this value",
    @"otherKey": @"remoteData.payload",
    @"some": @"more",
    @"JSON": @"keys",
    @"and": @"stuff",
};

Categories

  • Categories should be named for the sort of functionality they provide. Don't create umbrella categories. Umbrella categories are acceptable for grouping convenience methods.
  • Category methods should always be prefixed. be prefixed if they are part of a library that will be shared.
  • If you need to expose private methods for subclasses or unit testing, create a class extension named Class+Subclass.

About

Coding conventions for Objective-C projects

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published