- Identifiers
- Naming classes, protocols, categories
- Variables
- Methods
- Preprocessor Macros
- Functions
- Constants
- Enumerations
- Types Ans Structures
- Notifications
- Class Fields
- Class Properties
- Indents
- Long Lines
- Singletons
- Braces
- Pointers
- Blocks
- Project Structure
- Autogenerated Code
- Grouping Methods
- References
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
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 must match the names of the classes (interfaces, protocols). As for categories, it's the individual case described below.
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
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)
Use camelNotation with the first word lowecased.
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 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
Use the same rules as for class names.
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
Use the same rules as for class names.
Use the same rules as for class names.
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 are camelCased identifiers with lowercased first letter.
@interface A
{
NSInteger fieldName;
}
@end
Class fields are camelCased identifiers with lowercased first letter. Even CoreData table field names!
@interface User : NSManagedObject
@property (nonatomic, retain) NSNumber* userId;
@end
Don't use tabs.
Use 4 spaces.
Line length should not exceed 100 characters.
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];
Call a singleton instance access method sharedInstance
:
@interface MyCoolSingleton
+ (id)sharedInstance;
@end
...
MyCoolSingleton *coolSingleton =
(MyCoolSingleton *)[MyCoolSingleton sharedInstance];
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];
}
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;
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];
}];
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*
andUI*
class categories, and also categories for third-party classes), - AppDelegate
- Resources
- Supporting Files
Bad:
Good:
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.
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;
}
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