- Original link: The official raywenderlich.com objective-c style guide
- Original Author: raywenderlich.com Team
- Version: raywenderlich.com objective-c Coding Specification
- Translator: Sam Lau
As I'm preparing to mimic the hungry app, there may be some iOS developers involved in it. At this point, if everyone's objective-c coding style is not the same, it is not easy to maintain code consistency and difficult codes Review. So I searched the internet for the official Raywenderlich.com Objective-c style guide article on objective-c coding style, and felt that it could be used as the OBJECTIVE-C coding standard for this project, So just translate this article.
raywenderlich.com OBJECTIVE-C Coding Specification
This coding style guide outlines the coding specifications for raywenderlich.com, which may be truncated or modified.
Introduced
The reason we developed the OBJECTIVE-C coding specification is that we are able to keep the code in our books, tutorials and starter kits elegant and consistent. Even though we have many different authors to complete different books.
The coding specification here may be different from the other OBJECTIVE-C encoding specifications you see, because it is primarily for printing and web legibility.
About the author
This coding specification was created by a lot of raywenderlich.com team members under the leadership of Nicholas Waynik. Team members are: Soheil moayedi azarpour, Ricardo Rendon cepeda,tony Dahbura, Colin Eberhardt, Matt Galloway, Greg Heo, Matthijs Holl Emans,christopher Lapollo, Saul Mora, Andy Pereira, Mic Pringle, Pietro Rea, Cesare Rocchi, Marin Todorov, Nicholas Waynik and Ray Wenderlich.
We are also very grateful to the authors of the new York times and Robots & Pencils ' objective-c coding specifications. These two coding specifications provide a good starting point for the creation of this guide.
Background
Here are some official Apple documents about coding style, if something is not mentioned, you can find more details in the following documents:
- The OBJECTIVE-C programming Language
- Cocoa Fundamentals Guide
- Coding Guidelines for Cocoa
- IOS APP Programming Guide
Directory
- Language
- Code Organization
- Space
- Comments
- Named
- Method
- Variable
- Attribute Properties
- Dot symbol syntax
- Literal value
- Constant
- Enum type
- Case statement
- Private properties
- Boolean value
- Conditional statements
- Init method
- Class construction methods
- CGRect function
- Golden Path
- Error handling
- Single-Case mode
- Line break
- Xcode Project
Language
You should use US English.
Should:
UIColor *myColor = [UIColor whiteColor];
No:
UIColor *myColour = [UIColor whiteColor];
Code Organization
The classification method is used in the function grouping and protocol/delegate implementations to#pragma mark -follow the following general structure:
#pragma mark - Lifecycle
- (instancetype)init {}
- (void)dealloc {}
- (void)viewDidLoad {}
- (void)viewWillAppear:(BOOL)animated {}
- (void)didReceiveMemoryWarning {}
#pragma mark - Custom Accessors
- (void)setCustomProperty:(id)value {}
- (id)customProperty {}
#pragma mark - IBActions
- (IBAction)submitData:(id)sender {}
#pragma mark - Public
- (void)publicMethod {}
#pragma mark - Private
- (void)privateMethod {}
#pragma mark - Protocol conformance
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - NSCopying
- (id)copyWithZone:(NSZone *)zone {}
#pragma mark - NSObject
- (NSString *)description {}
Space
- Indent uses 4 spaces to make sure that you set it in Xcode preferences. (raywenderlich.com use 2 spaces)
- Method braces and other curly braces (if//else/switchwhileetc.) Always open in the same line statement but close in the new row.
Should:
if (user.isHappy) { //Do something} else { //Do something else}
No:
if (user.isHappy){ //Do something}else { //Do something else}
- There should be only one row between the methods, which makes it visually clearer and easier to organize. The whitespace within the method should be separated from the function, but is usually drawn out to become a new method.
- Prefer to use auto-synthesis. But if necessary,@synthesizeand@dynamicshould declare a new row in each of the implementations.
- You should avoid calling methods in a colon-aligned manner. Because sometimes a method signature may have more than 3 colons and colon alignments, the code is easier to read. Do not do this, although the colon-aligned method contains a block of code, because Xcode's alignment makes it illegible.
Should:
// blocks are easily readable
[UIView animateWithDuration:1.0 animations:^{
// something
} completion:^(BOOL finished) {
// something
}];
No:
// colon-aligning makes the block indentation hard to read
[UIView animateWithDuration:1.0
animations:^{
// something
}
completion:^(BOOL finished) {
// something
}];
Comments
When a comment is needed, the comment should be used to explain why This particular code is doing so. Any comments that are used must be kept up-to-date or deleted.
Block annotations are generally avoided because the code is as self-explanatory as possible, and comments are required only if there are intermittent or a few lines of code. exception: This does not apply to comments generated in the document
Named
Apple naming rules persist as much as possible, especially with these associated memory management rules (NARC).
Long, descriptive methods and variable names are good.
Should:
UIButton *settingsButton;
No:
UIButton *setBut;
A three-character prefix should often be named for classes and constants, but should be ignored in the entity name of core data. For official raywenderlich.com books, starter kits or tutorials, the prefix ' RWT ' should be used.
Constants should use a camel-like naming convention, with all the first letters capitalized and prefixed with the class name.
Should:
static NSTimeInterval const RWTTutorialViewControllerNavigationFadeAnimationDuration = 0.3;
No:
static NSTimeInterval const fadetime = 1.7;
The property is also used in camel-style, but the first word of the first letter is lowercase. Use auto-synthesis for attributes instead of writing @ synthesize statements manually unless you have a good reason.
Should:
@property (strong, nonatomic) NSString *descriptiveVariableName;
No:
id varnm;
Underline
When using attributes, instance variables should be usedself.to access and change. This means that all properties will be visually different because they are in front of each otherself..
But there is one exception: in the initialization method, instance variables (for example, _variablename) should be used directly to avoid getters/setters potential side effects.
Local variables should not contain underscores.
Method
In a method signature, you should have a space after the method type (-/+ symbol). There should also be a space between each segment of the method (in Apple's style). You should include a descriptive keyword before the parameter to describe the parameter.
The use of the word "and" should be preserved. It should not be used for multiple parameters to illustrate, as ininitWithWidth:heightthe following example:
Should:
- (void)setExampleText:(NSString *)text image:(UIImage *)image;
- (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag;
- (id)viewWithTag:(NSInteger)tag;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
No:
-(void)setT:(NSString *)text i:(UIImage *)image;
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;
- (id)taggedView:(NSInteger)tag;
- (instancetype)initWithWidth:(CGFloat)width andHeight:(CGFloat)height;
- (instancetype)initWith:(int)width and:(int)height; // Never do this.
Variable
Variables should be named in a descriptive manner as much as possible. The name of a single character variable should be avoided, except in thefor()loop.
An asterisk indicates that the variable is a pointer. For example, theNSString *textNSString* textconstants are neither and notNSString * text, except for some special cases.
Private variables should be used as much as possible instead of instance variables. Although using instance variables is an efficient way, it is more inclined to use attributes to maintain code consistency.
Direct access to instance variables by using the ' Back ' property (_variable, preceded by an underscore in the variable name) should be avoided, except in the initialization method (,, etc...initinitWithCoder:),deallocmethods and custom setters and getters. For more information on how to use the accessor method directly in the initialization method and Dealloc, see here
Should:
@interface RWTTutorial : NSObject@property (strong, nonatomic) NSString *tutorialName;@end
No:
@interface RWTTutorial : NSObject { NSString *tutorialName;}
Attribute Properties
All attribute attributes should be explicitly listed to help the novice read the code. The order of attribute attributes should be storage, atomicity, and automatically generated code when interface builder connects UI elements.
Should:
@property (weak, nonatomic) IBOutlet UIView *containerView;@property (strong, nonatomic) NSString *tutorialName;
No:
@property (nonatomic, weak) IBOutlet UIView *containerView;@property (nonatomic) NSString *tutorialName;
NSString should be usedcopyinsteadstrongof attribute attributes.
Why? Even if you declare aNSStringproperty, someone might passNSMutableStringin an instance and then modify it without your attention.
Should:
@property (copy, nonatomic) NSString *tutorialName;
No:
@property (strong, nonatomic) NSString *tutorialName;
Dot symbol syntax
Point syntax is a convenient way to encapsulate access to method calls. When you use the DOT syntax, properties are still accessed or modified by using getter or setter methods. To learn more, read here
Point syntax should always be used to access and modify properties, because it makes the code more concise. [] symbols are more inclined to use in other examples.
Should:
NSInteger arrayCount = [self.array count];
view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication].delegate;
No:
NSInteger arrayCount = self.array.count;
[view setBackgroundColor:[UIColor orangeColor]];
UIApplication.sharedApplication.delegate;
Literal value
NSString,NSDictionary,NSArray, andNSNumberthe literal value should be used when creating immutable instances of these classes. Please pay special attentionnilto values that cannot be passedNSArrayin and literalNSDictionary, because this will cause crash.
Should:
NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingStreetNumber = @10018;
No:
NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];
NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill", @"Mobile Web", nil];
NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];
NSNumber *buildingStreetNumber = [NSNumber numberWithInteger:10018];
Constant
Constants are easy to re-use and can be quickly modified without the need to find and replace them. Constants should bestaticdeclared instead#defineof used, unless the macro is explicitly used.
Should:
static NSString * const RWTAboutViewControllerCompanyName = @"RayWenderlich.com";static CGFloat const RWTImageThumbnailHeight = 50.0;
No:
#define CompanyName @"RayWenderlich.com"#define thumbnailHeight 2
Enum type
When usedenum, it is recommended to use the new fixed base type specification as it has stronger type checking and code completion. The SDK now has a macroNS_ENUM()to help and encourage you to use a fixed base type.
For example:
typedef NS_ENUM(NSInteger, RWTLeftMenuTopItemType) { RWTLeftMenuTopItemMain, RWTLeftMenuTopItemShows, RWTLeftMenuTopItemSchedule};
You can also assign values explicitly (show the old K-style constant definition):
typedef NS_ENUM(NSInteger, RWTGlobalConstants) { RWTPinSizeMin = 1, RWTPinSizeMax = 5, RWTPinCountMin = 100, RWTPinCountMax = 500,};
The old K-style constant definition should be avoided unless you write code for core Foundation C.
No:
enum GlobalConstants { kMaxPinSize = 5, kMaxPinCount = 500,};
Case statement
Curly braces are not required in case statements unless the compiler enforces the requirements. When a case statement contains multiple lines of code, the curly braces should be added.
switch (condition) {
case 1:
// ...
break;
case 2: {
// ...
// Multi-line example using braces
break;
}
case 3:
// ...
break;
default:
// ...
break;
}
Many times, when the same code is used by multiple cases, a fall-through should be used. One fall-through is to remove the ' break ' statement at the end of the case, allowing the execution process to jump to the next value. For the code to be clearer, a fall-through needs to be commented out.
switch (condition) {
case 1:
// ** fall-through! **
case 2:
// code executed for values 1 and 2
break;
default:
// ...
break;
}
The ' default ' is not required when using the enum type with switch. For example:
RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;
switch (menuType) {
case RWTLeftMenuTopItemMain:
// ...
break;
case RWTLeftMenuTopItemShows:
// ...
break;
case RWTLeftMenuTopItemSchedule:
// ...
break;
}
Private properties
Private properties should be declared in class extensions (anonymous classification) in the implementation file of the class, and named classifications (such asRWTPrivateorprivate) should never be used unless the other classes are extended. Anonymous categorization should be exposed to the test by using a naming convention that uses the
For example:
@interface RWTDetailViewController ()
@property (strong, nonatomic) GADBannerView *googleAdView;
@property (strong, nonatomic) ADBannerView *iAdView;
@property (strong, nonatomic) UIWebView *adXWebView;
@end
Boolean value
Objective-c useYESandNO. Becausetrueandfalseshould only be used in corefoundation,c or C + + code. Sincenilparsing is madeNO, there is no need to compare in conditional statements. Do not take something directly with theYEScomparison, because itYESis defined as 1 and oneBOOLcan be set to 8 bits.
This is to be considered in order to maintain consistency in different documents and to be more visually concise.
Should:
if (someObject) {}if (![anotherObject boolValue]) {}
No:
if (someObject == nil) {}if ([anotherObject boolValue] == NO) {}if (isAwesome == YES) {} // Never do this.if (isAwesome == true) {} // Never do this.
If theBOOLname of the property is an adjective, the attribute can ignore the "is" prefix, but specify the customary name of the get accessor. For example:
@property (assign, getter=isEditable) BOOL editable;
Text and examples from here refer to cocoa naming guidelines
Conditional statements
The conditional statement body should be surrounded with curly braces in order to prevent errors, even if the conditional statement body can be written without curly braces (for example, with just one line of code). These errors include adding a second line of code and expecting it to be an if statement; Also, even more dangerous defect can occur in an if statement where a line of code is commented, and then the next line of code unknowingly becomes part of the IF statement. In addition, this style is consistent with the style of other conditional statements, so it's easier to read.
Should:
if (!error) { return success;}
No:
if (!error) return success;
Or
if (!error) return success;
Ternary operator
Ternary operators are used when it is necessary to improve the clarity and simplicity of the code?:. A single conditional evaluation often requires it. When multiple criteria are evaluated, the code is more readable if you useifa statement or re-form an instance variable. In general, it is best to use the ternary operator when assigning values based on conditions.
Non-boolean variables are compared to something, and parentheses () improve readability. If the variable being compared is a Boolean type, then no parentheses are required.
Should:
NSInteger value = 5;result = (value != 0) ? x : y;BOOL isHorizontal = YES;result = isHorizontal ? x : y;
No:
result = a > b ? x = c > d ? c : d : y;
Init method
The Init method should follow the naming rules for Apple-generated code templates. The return type should be usedinstancetypeinstead ofid
- (instancetype)init { self = [super init]; if (self) { // ... } return self;}
View articles about Instancetype class Constructor Methods
Class construction methods
When a class construction method is used, it should return the type to beinstancetypeinstead ofid. This ensures that the compiler correctly infers the result type.
@interface Airplane+ (instancetype)airplaneWithType:(RWTAirplaneType)type;@end
For more instancetype information, please see nshipster.com
CGRect function
When accessedCGRect,,xywidth, orheightwhen, it should be accessed using aCGGeometryfunction rather than directly through the struct. References to AppleCGGeometry:
All functions in this reference document accept CGRect as input and implicitly standardize these rectangles when calculating their results. Therefore, your application should avoid directly accessing and modifying the data stored in the CGRect structure. Instead, use these functions to manipulate the rectangles and get their attributes.
Should:
CGRect frame = self.view.frame;
CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);
CGRect frame = CGRectMake(0.0, 0.0, width, height);
No:
CGRect frame = self.view.frame;
CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
CGRect frame = (CGRect){ .origin = CGPointZero, .size = frame.size };
Golden Path
When using conditional statement encoding, the left-hand side code should be "golden" or "Happy" path.ifthat is, do not nest statements, multiple return statements are OK.
Should:
- (void)someMethod { if (![someOther boolValue]) { return; } //Do something important}
No:
- (void)someMethod { if ([someOther boolValue]) { //Do something important }}
Error handling
When the method returns an error parameter by reference, the return value is judged instead of the error variable.
Should:
NSError *error;if (![self trySomethingWithError:&error]) { // Handle Error}
No:
NSError *error;[self trySomethingWithError:&error];if (error) { // Handle Error}
In the case of success, some Apple APIs record the garbage value (garbage values) to the error parameter (if non-null), then judging the error value results in false negative values and crash.
Single-Case mode
Singleton objects should use thread-safe mode to create shared instances.
+ (instancetype)sharedInstance {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
This prevents possible and sometimes prolific crashes.
Line break
Line breaks are an important topic because the style guides are primarily for printing and for readability on the web.
For example:
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
A long line of code should be divided into two lines of code and the next line separated by two spaces.
self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
Xcode Project
Physical files should be synchronized with the Xcode project file to avoid file expansion. The creation of any Xcode grouping should be reflected in the file system file. The code is not only grouped by type , but can also be grouped by function , which makes the code clearer.
Open the "Treat Warnings as Errors as possible at Target's build settings, and enable the following additional Warnings. If you need to ignore special warnings, use Clang ' s pragma feature.
Other OBJECTIVE-C Coding Specifications
If our coding specifications don't match your tastes, you can look at other coding specifications:
- Robots & Pencils
- New York Times
- Google
- GitHub
- Adium
- Sam Soffes
- Cocoadevcentral
- Luke Redpath
- Marcus Zarra
From: http://www.jianshu.com/p/8b76814b3663?utm_campaign=hugo&utm_medium=reader_share&utm_content=note# Ternary-operator
raywenderlich.com OBJECTIVE-C Coding Specification