-
Notifications
You must be signed in to change notification settings - Fork 105
Objective C Style Guide
Joel Fischer edited this page May 13, 2020
·
8 revisions
These guidelines build on the Apple Coding Guidelines for Cocoa.
Partially based on the Github, New York Times, and Dropbox style guides.
- Spaces not tabs (4 spaces per indentation)
- End files with a newline
- Use whitespace to divide code into chunks
- No trailing whitespace on lines
- Block comments should only exist for generated documentation.
- Inline comments should be used only if the time spent writing the comments is less than the time it would take someone with zero context to understand what you are doing. If you find yourself writing a lot of comments, the code should probably be broken apart or refactored for clarity.
-
#pragma mark
methods into logical clusters. Use#pragma mark -
for major functionality groups,#pragma mark
for minor functionality groups.
- Label
TODO
andFIXME
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!
- Order is: 1. Your own header (if in .m) 2. Framework headers 3. Local headers
- Import alphabetically.
- Use class forwarding in .h files whenever possible.
- Use
strong
properties only if exposing a mutable object, or one that does not conform to<NSCopying>
. Prefercopy
in other instances. - Properties should be declared
nonatomic
by default unless there is a very good reason to useatomic
, which will be rare. - Properties should be accessed and set using dot-syntax.
- Collections should rarely, or never, be exposed publicly as mutable, they should also be read-only as much as possible. Collections that are mutable in the implementation should be exposed as so:
file.h
@property (nonatomic, readonly) NSArray *array;
file.m
@property (nonatomic) NSMutableArray *mutableArray;
- (NSArray *)array {
return [self.mutableArray copy];
}
- 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.
- Always initialize local variables, they will not be automatically initialized to
nil
or0
.
- 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.
- 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
.
- Access properties and structs by dot-syntax, everything else (including idempotent methods) via bracket syntax.
- 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
, andNSNumber
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
};
- To declare enumerations, use
NS_ENUM
. To declare options (bitmasks) useNS_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
};
- 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 should always contain braces.
- Comparisons should always be explicit except for
BOOL
values.BOOL
values are actually asigned char
, and explicit comparisons can lead to incorrect results in certain cases, such as setting aBOOL
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;
- 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.
- Only iterate over immutable collections. Convert mutable collections to immutable ones
Copyright 2021 SmartDeviceLink Consortium