Skip to content

Latest commit

 

History

History
529 lines (327 loc) · 12.4 KB

objective-c-coding-conventions.md

File metadata and controls

529 lines (327 loc) · 12.4 KB

Objective-C Coding Conventions

  1. Identifiers
  2. Naming classes, protocols, categories
  3. Variables
  4. Methods
  5. Preprocessor Macros
  6. Functions
  7. Constants
  8. Enumerations
  9. Types Ans Structures
  10. Notifications
  11. Class Fields
  12. Class Properties
  13. Indents
  14. Long Lines
  15. Singletons
  16. Braces
  17. Pointers
  18. Blocks
  19. Project Structure
  20. Autogenerated Code
  21. Grouping Methods
  22. References

Identifiers

Identifiers (variable names, class names, functions, constants, types, and other elements of the source code) must be clear and without abbreviations.

Exceptions are described here (also database may be shortened to db).

Use camelNotation if the identifier is more than one word. No underscores, except as noted below.

Bad: pushNotif, is_sel

Good: pushNotification, isSelected

Naming classes, protocols, categories

Class, protocol and category names must consist of words and/or generally accepted abbreviations (see above), each of which begins with a capital letter. If the class is not related to MVC/GUI, and implements some specific (business) logic or functionality, or we develop a library/framework, the prefix of the capital letters should be added.

Bad: MainVC (for controller), ContactTableContent (for table cell), CustomSlider (inherited from UIView)

Good: MainViewController, ContactTableViewCell/ContactCell, CustomSliderView

For framework:

Bad: ViewController

Good: MLSViewController

For Facebook:

Bad: LoginFacebook, FacebookWallMessage

Good: FBLoginHelper, FBWallMessageService (something like that ;))

For RESTful web services:

Bad: RestfulRequest, RestWebServiceResponse

Good: RESTService, RESTRequest, RESTResponse

The names of the base classes, which, logically, are abstract (although the latter are not supported in Objective-C), must start with the word Base. For example, BaseSearchEngine, BaseViewController.

Ideally, the abstract method bodies should not be empty. Those methods should throw exceptions instead.

@interface BaseSearchEngine 

- (void)search:(Query *)aQuery;

@end


@implementation BaseSearchEngine

- (void)search:(Query *)aQuery 
{
    @throw [NSException exceptionWithName:@"This method is abstract!" 
                                   reason:@"You should not invoke "\
                                          "this method." 
                                 userInfo:nil];
}

@end

File Names

File names must match the names of the classes (interfaces, protocols). As for categories, it's the individual case described below.

Protocols

Protocols for delegate, dataSource and other interfaces should be named with the interface name and the word Delegate, DataSource, etc. at the end. If you can not figure out the last word, you should use the word Protocol.

Should you extract protocols into separate header files? Yes, if interface declarations are too large.

@interface MainViewController -> @protocol MainViewControllerDelegate
@interface ClientTableView -> @protocol ClientTableViewDataSource
@interface AsynchronousImageProcessor -> @protocol AsynchronousImageProcessorProtocol

Categories

Category must have a clear title, if you extend the functionality of a particular class. For example,

@interface NSImage(Base64)

If you can not describe all added functionality in one word, use the word Extra.

@interface NSImage(Base64)
@interface NSData(Extra)

File names for categories: NSImage+Base64.h (.m), NSData+Extra.h (.m)

Variables

Use camelNotation with the first word lowecased.

Methods

Read this and this.

Regarding the spaces in method declarations, follow Apple official documentation and Xcode-generated code:

- (NSArray *)arrayByAddingObjectsFromArray:(NSArray *)otherArray;

Put a space before return value type (after +/-) and also in a parentheses, if the parameter is a pointer. Don't put spaces after parentheses.

Bad:

+(UIColor*)colorWithPatternImage:(UIImage*)image;
+ (UIColor *) colorWithWhite:(CGFloat) white alpha:(CGFloat) alpha;

Good:

+ (UIColor *)colorWithPatternImage:(UIImage *)image;
+ (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha;

Preprocessor Macros

Preprocessor directives are #define, #ifdef and things like that.

For macro names use the whole words without abbreviations (except for common acronyms, see above), and underscores.

Bad: debug, distrConfig

Good: DEBUG, DISTRIBUTION_CONFIGURATION

Example:

#ifndef DEBUG
#define DISTRIBUTION_CONFIGURATION
#endif

Functions

Use the same rules as for class names.

Constants

Start with a lowercase letter k, continue all the words with a first capital letter. Abbreviations should be uppercased.

Bad: ST_BAR_TITLE, CELL_NAME

Good: kStatusBarTitle, kCellName, kRESTWebService

Enumerations

Use the same rules as for class names.

Types Ans Structures

Use the same rules as for class names.

Notifications

Same as for class names, but with the word Notification at the end.

Bad:

const NSString* MLSNotifySalary = @"MLSNotifySalary";

Good:

const NSString* MLSSalaryNotification = @"MLSSalaryNotification";

Class Fields

Class fields are camelCased identifiers with lowercased first letter.

@interface A 
{
    NSInteger fieldName;
}
@end

Class Properties

Class fields are camelCased identifiers with lowercased first letter. Even CoreData table field names!

@interface User : NSManagedObject 

@property (nonatomic, retain) NSNumber* userId;

@end

Indents

Don't use tabs.

Use 4 spaces.

Line length should not exceed 100 characters.

Long Lines

When you declare, define or call a method with a long list of parameters, align the names of the arguments by colon (one line - one parameter).

Bad:

- (NSColor *)colorWithCalibratedHue:(CGFloat)aHue saturation: (CGFloat)aSaturation brightness:(CGFloat)aBrightness alpha:(CGFloat)anAlpha;

Good:

- (NSColor *)colorWithCalibratedHue:(CGFloat)aHue 
                         saturation:(CGFloat)aSaturation 
                         brightness:(CGFloat)aBrightness 
                              alpha:(CGFloat)anAlpha; 

Do not make nested calls methods in such cases, it is better to store the result of a method call in a local variable.

Bad:

[view setBackgroundColor:[NSColor colorWithCalibratedHue:0.10 saturation:0.82 brightness:0.89 alpha:1.0]];

Good:

NSColor *color = [NSColor colorWithCalibratedHue:0.10 
                                      saturation:0.82 
                                      brightness:0.89 
                                           alpha:1.00];

[view setBackgroundColor: color];

It is allowed to leave multiple parameters on a single line in the case of standard methods usage. Here, the first parameter of each line must be aligned to the colon of the first parameter.

[NSTimer scheduledTimerWithTimeInterval:kTimeInterval target:self
                               selector:@selector(fireMethod)
                               userInfo:nil repeats:YES];

Singletons

Call a singleton instance access method sharedInstance:

@interface MyCoolSingleton 

+ (id)sharedInstance;

@end

...

MyCoolSingleton *coolSingleton = 
        (MyCoolSingleton *)[MyCoolSingleton sharedInstance];

Braces

An opening brace should always be on a new line, no exceptions:

@interface Person : NSObject
{
    NSString *name;
}
+ (Person *)personWithName:(NSString *)personName 
{
    if (personName == nil)
    {
        return nil;
    }
    // ...
}

Always use braces in conditional statements, even if there is only one operator:

if (person)
{
    [person release];
}

Pointers

When using pointers, always put a space between class name and asterisk.

Bad:

Person* person = ...;

Good:

Person *person = ...;

Bad:

+ (Person*)personWithName:(NSString*)personName;

Good:

+ (Person *)personWithName:(NSString *)personName; 

Blocks

If you need to pass a block as a value of the parameter when calling the function (sending a message), it is recommended to define a variable:

void(^success)(NSURLRequest *,NSHTTPURLResponse *,id) =
    ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) 
{
    // ...
};

[AFJSONRequestOperation JSONRequestOperationWithRequest:request
                                                success:success
                                                failure:nil];

However, small blocks may be passed without additional variable usage:

[UIView animateWithDuration:kAnimationDuration
                 animations:^{
                     [someView setAlpha:1.f];
                 }];

Project Structure

The structure of the project should be simple and clear. Classes should be grouped by purpose or pattern the class implements.

Root group classes should be in the following order:

  • Models
  • Controllers
  • Views
  • Managers
  • Factories
  • Builders
  • Helpers
  • Wrappers
  • Categories (all NS* and UI* class categories, and also categories for third-party classes),
  • AppDelegate
  • Resources
  • Supporting Files

Bad:

Bad Project Structure

Good:

Good Project Structure

The next level of grouping is the meaning of class/interface etc. For example, controllers must be grouped by application screens.

The folders in a file system (on hard drive) must have the same structure as the Xcode project.

Autogenerated Code

When you create a new class in Xcode (controller, for example), remove all the autogenerated crap if you are not going to override methods right now.

There should be no such things in a source code:

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {        
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

Grouping Methods

To improve the readability of the code (and navigation through it), use the following macro:

#pragma mark - %group name%

For example,

@implementation MarkViewController

#pragma mark - lifecycle

- (id)init;

- (void)dealloc;

#pragma mark - view lifecycle

- (void)viewDidLoad;

- (void)viewWillAppear:(BOOL)animated;

- (void)viewDidAppear:(BOOL)animated;

- (void)viewWillDisappear:(BOOL)animated;

- (void)viewDidDisappear:(BOOL)animated;

#pragma mark - appearance

- (NSUInteger)supportedInterfaceOrientations;

- (BOOL)prefersStatusBarHidden;

- (void)viewWillLayoutSubviews

- (void)viewDidLayoutSubviews

#pragma mark - public methods

- (NSString *)getStringFromData:(NSData *)data;

#pragma mark - actions

- (IBAction)buttonPressed;

#pragma mark - private methods

- (void)prepareTheKraken;

#pragma mark - delegate methods

- (void)gotResponseFromObject:(id)object withData:(NSDAta *)data;

@end

References