Reprint--OBJECTIVE-C code specification [translate]

Source: Internet
Author: User
Tags case statement coding standards constant definition
Original link: The official raywenderlich.com Objective-C style guide
Original author: raywenderlich.com Team
Translation from: raywenderlich.com Objective-C coding specification
Translator: Sam Lau
Since I am preparing to imitate this app, there may be some iOS developers involved at that time. At this time, if everyone's Objective-C coding style is different, it is not easy to maintain code consistency and difficult to Code Review. So I searched the Internet for the official raywenderlich.com Objective-C style guide about Objective-C coding style. I thought it could be used as the Objective-C coding standard for this project, so I translated this article.

raywenderlich.com Objective-C coding specification
This coding style guide summarizes the coding specifications of raywenderlich.com, which may be slightly deleted or modified.

Introduction
The reason we developed Objective-C coding standards is that we are able to maintain elegance and consistency in the code in our books, tutorials, and starter kits. Even if we have many different authors to complete different books.

This encoding specification may be different from other Objective-C encoding specifications you see, because it is mainly for print and web legibility.

About the author
This coding specification was created by many members from the raywenderlich.com team under the leadership of Nicholas Waynik. Team members are: Soheil Moayedi Azarpour, Ricardo Rendon Cepeda, Tony Dahbura, Colin Eberhardt, Matt Galloway, Greg Heo, Matthijs Hollemans, Christopher LaPollo, Saul Mora, Andy Pereira, Mic Pringle, Pietro Rea, Cesare Waynik, Marinlas Toni And Ray Wenderlich

We are also very grateful to the authors of the New York Times and Robots & Pencils ’Objective-C coding specification. These two coding standards provide a good starting point for the creation of this guide.

background
Here are some official Apple documentation on coding styles. 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
Language
US English should be used.

should:

UIColor * myColor = [UIColor whiteColor];
Should not:

UIColor * myColour = [UIColor whiteColor];
 

Code organization
Use #pragma mark-to classify methods in function grouping and protocol / delegate implementations, following the 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
Use 4 spaces for indentation, make sure to set it in Xcode preferences. (raywenderlich.com uses 2 spaces)
Method curly braces and other curly braces (if / else / switch / while, etc.) are always opened on the same statement but closed on a new line.
should:

if (user.isHappy) {
    // Do something
} else {
    // Do something else
}
Should not:

if (user.isHappy)
{
  // Do something
}
else {
  // Do something else
}
There should be one and only one line between methods, which helps to be more visually clear and easier to organize. The white space in the method should separate the functions, but it is usually extracted as a new method.
Use auto-synthesis first. But if necessary, @synthesize and @dynamic should each declare a new line in the implementation.
Avoid calling methods in a colon-aligned manner. Because sometimes the method signature may have more than 3 colons and colon alignment makes the code more readable. Please don't do this, although the colon-aligned method contains code blocks, as Xcode's alignment makes it hard to read.
should:

// blocks are easily readable
[UIView animateWithDuration: 1.0 animations: ^ {
  // something
} completion: ^ (BOOL finished) {
  // something
}];
Should not:

// colon-aligning makes the block indentation hard to read
[UIView animateWithDuration: 1.0
                 animations: ^ {
                     // something
                 }
                 completion: ^ (BOOL finished) {
                     // something
                 }];
 

Comment
When comments are needed, they should be used to explain why this particular code does it. Any comments used must be kept up-to-date or deleted.

Block comments are generally avoided, because the code is as self-explanatory as possible, and comments are only needed if it is intermittent or a few lines of code. Exception: this does not apply to comments in generated documentation

 

name
Apple's naming rules are as consistent as possible, especially the memory management rules (NARC) related to these.

Long, descriptive method and variable naming is fine.

should:

UIButton * settingsButton;
Should not:

UIButton * setBut;
The three-character prefix should often be used for class and constant names, but should be ignored in Core Data entity names. For official raywenderlich.com books, starter kits or tutorials, the prefix 'RWT' should be used.

Constants should use camel case naming convention, capitalizing all words and prefixing them with class names.

should:

static NSTimeInterval const RWTTutorialViewControllerNavigationFadeAnimationDuration = 0.3;
Should not:

static NSTimeInterval const fadetime = 1.7;
Attributes are also humped, but the first letter of the first word is lowercase. Use auto-synthesis for attributes instead of manually writing @synthesize statements unless you have a good reason.

should:

@property (strong, nonatomic) NSString * descriptiveVariableName;
Should not:

id varnm;
 

Underline
When using properties, instance variables should be accessed and changed using self. This means that all properties will have different visual effects, because they are preceded by self.

But there is a special case: In the initialization method, instance variables (for example, _variableName) should be used directly to avoid the potential side effects of getters / setters.

Local variables should not contain underscores.

 

method
In method signatures, there should be a space after the method type (-/ + sign). There should also be a space between the sections of the method (in Apple's style). A descriptive keyword should be included before the parameter to describe the parameter.

The use of the word "and" should be retained. It should not be used for multiple parameters to illustrate, like the following example of initWithWidth: height:

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;
Should not:

-(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 are named as descriptively as possible. Single character variable naming should be avoided as much as possible, except in a for () loop.

The asterisk indicates that the variable is a pointer. For example, NSString * text is neither NSString * text nor NSString * text, except for constants in special cases.

Private variables should replace the use of instance variables whenever possible. Although using instance variables is an effective way, it prefers to use attributes to maintain code consistency.

Direct access to instance variables by using the ‘back’ property (_variable, with an underscore in front of the variable name) should be avoided, except in the initialization methods (init, initWithCoder :, etc ...), the dealloc method and custom setters and getters. For more information on how to use Accessor methods directly in the initialization method and dealloc, check here

should:

@interface RWTTutorial: NSObject

@property (strong, nonatomic) NSString * tutorialName;

@end
Should not:

@interface RWTTutorial: NSObject {
  NSString * tutorialName;
}
 

Attributes characteristic
All property attributes should be listed explicitly to help novices read the code. The order of attribute properties should be storage, atomicity, which is consistent with the automatically generated code when connecting UI elements in Interface Builder.

should:

@property (weak, nonatomic) IBOutlet UIView * containerView;
@property (strong, nonatomic) NSString * tutorialName;
Should not:

@property (nonatomic, weak) IBOutlet UIView * containerView;
@property (nonatomic) NSString * tutorialName;
NSString should use the copy attribute instead of the strong attribute.

why? Even if you declare a property of NSString, someone may pass in an instance of NSMutableString and modify it without your attention.

should:

@property (copy, nonatomic) NSString * tutorialName;
Should not:

@property (strong, nonatomic) NSString * tutorialName;
 

Dot notation syntax
Dot syntax is a convenient way to encapsulate access method calls. When you use dot syntax, properties are still accessed or modified by using getter or setter methods. Want to know more, read here

Dot syntax should always be used to access and modify attributes, as it makes the code more concise. The [] symbol is more used in other examples.

should:

NSInteger arrayCount = [self.array count];
view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication] .delegate;
Should not:

NSInteger arrayCount = self.array.count;
[view setBackgroundColor: [UIColor orangeColor]];
UIApplication.sharedApplication.delegate;
 

Literal value
The literal values of NSString, NSDictionary, NSArray, and NSNumber should be used when creating immutable instances of these classes. Please note that nil values cannot be passed to NSArray and NSDictionary literals, as this will cause a 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;
Should not:

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 reuse and quickly modify values without having to find and replace. Constants should be declared using static instead of #define, unless macros are used explicitly.

should:

static NSString * const RWTAboutViewControllerCompanyName = @ "RayWenderlich.com";

static CGFloat const RWTImageThumbnailHeight = 50.0;
Should not:

#define CompanyName @ "RayWenderlich.com"

#define thumbnailHeight 2
 

Enumerated type
When using enum, the new fixed base type specification is recommended because it has stronger type checking and code completion. The SDK now has a macro NS_ENUM () to help and encourage you to use a fixed base type.

E.g:

typedef NS_ENUM (NSInteger, RWTLeftMenuTopItemType) {
  RWTLeftMenuTopItemMain,
  RWTLeftMenuTopItemShows,
  RWTLeftMenuTopItemSchedule
};
You can also assign explicitly (show the old k-style constant definition):

typedef NS_ENUM (NSInteger, RWTGlobalConstants) {
  RWTPinSizeMin = 1,
  RWTPinSizeMax = 5,
  RWTPinCountMin = 100,
  RWTPinCountMax = 500,
};
Old k-style constant definitions should be avoided unless you write Core Foundation C code.

Should not:

enum GlobalConstants {
  kMaxPinSize = 5,
  kMaxPinCount = 500,
};
 

Case statement
Braces are not required in case statements unless the compiler mandates them. When a case statement contains multiple lines of code, braces should be added.

switch (condition) {
  case 1:
    // ...
    break;
  case 2: {
    // ...
    // Multi-line example using braces
    break;
  }
  case 3:
    // ...
    break;
  default:
    // ...
    break;
}
Many times, a fall-through should be used when the same code is used in multiple cases. A fall-through is to remove the 'break' statement at the end of the case, which allows the execution flow to jump to the next case value. To make the code clearer, a fall-through needs to be commented.

switch (condition) {
  case 1:
    // ** fall-through! **
  case 2:
    // code executed for values 1 and 2
    break;
  default:
    // ...
    break;
}
When using an enum type in a switch, 'default' is not needed. E.g:

RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;

switch (menuType) {
  case RWTLeftMenuTopItemMain:
    // ...
    break;
  case RWTLeftMenuTopItemShows:
    // ...
    break;
  case RWTLeftMenuTopItemSchedule:
    // ...
    break;
}
 

Private property
Private attributes should be declared in the class extension (anonymous classification) in the class's implementation file. Named classifications (such as RWTPrivate or private) should never be used unless they extend other classes. Anonymous classification should be exposed to tests by using the naming convention of <headerfile> + Private.h file.

E.g:

@interface RWTDetailViewController ()

@property (strong, nonatomic) GADBannerView * googleAdView;
@property (strong, nonatomic) ADBannerView * iAdView;
@property (strong, nonatomic) UIWebView * adXWebView;

@end
 

Boolean value
Objective-C uses YES and NO. Because true and false should only be used in CoreFoundation, C or C ++ code. Since nil resolves to NO, there is no need to compare in conditional statements. Don't compare something directly with YES, because YES is defined as 1 and a BOOL can be set to 8 bits.

This is considered to be consistent across documents and more visually concise.

should:

if (someObject) ()
if (! [anotherObject boolValue]) {}
Should not:

if (someObject == nil) ()
if ([anotherObject boolValue] == NO) {}
if (isAwesome == YES) {} // Never do this.
if (isAwesome == true) {} // Never do this.
If the name of the BOOL attribute is an adjective, the attribute can ignore the "is" prefix, but specify the customary name of the get accessor. E.g:

@property (assign, getter = isEditable) BOOL editable;
Text and examples are quoted from the Cocoa Naming Guidelines

 

Conditional statements
The body of a conditional statement should be surrounded by braces to prevent errors, even if the body of the conditional statement can be written without curly braces (for example, using only one line of code). These errors include adding a second line of code and expecting it to be an if statement; moreover, even more dangerous defect may occur in an if statement where one 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 is easier to read.

should:

if (! error) {
  return success;
}
Should not:

if (! error)
  return success;
or

if (! error) return success;
 

Ternary operator
The ternary operator?: Is used when you need to improve the clarity and conciseness of your code. It is often needed for single condition evaluation. When evaluating multiple conditions, the code is more readable if you use if statements or reconstitute instance variables. In general, it is best to use the ternary operator when you are assigning values based on conditions.

Non-boolean variables are compared to something, and parentheses () improve readability. If the variable being compared is of type boolean, then no parentheses are required.

should:

NSInteger value = 5;
result = (value! = 0)? x: y;

BOOL isHorizontal = YES;
result = isHorizontal? x: y;
Should not:

result = a> b? x = c> d? c: d: y;
 

Init method
The Init method should follow the naming rules of Apple generated code templates. Return type should use instancetype instead of id

-(instancetype) init {
  self = [super init];
  if (self) {
    // ...
  }
  return self;
}
See article about instancetype Class Constructor Methods

 

Class constructor
When a class constructor is used, it should return an instancetype instead of an id. 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 accessing x, y, width, or height in CGRect, you should use the CGGeometry function instead of directly through the structure. Quoting Apple's CGGeometry:

All functions in this reference document take CGRect structures as input and implicitly normalize these rectangles when calculating their results. Therefore, your application should avoid directly accessing and modifying data stored in CGRect data structures. Instead, use these functions to manipulate rectangles and get their properties.

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);
Should not:

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 coding, the code on the left should be the "golden" or "happy" path. That is, do not nest if statements, and multiple return statements are also OK.

should:

-(void) someMethod {
  if (! [someOther boolValue]) {
    return;
  }

  // Do something important
}
Should not:

-(void) someMethod {
  if ([someOther boolValue]) {
    // Do something important
  }
}
 

Error handling
When a method returns an error parameter by reference, determine the return value instead of the error variable.

should:

NSError * error;
if (! [self trySomethingWithError: & error]) {
  // Handle Error
}
Should not:

NSError * error;
[self trySomethingWithError: & error];
if (error) {
  // Handle Error
}
In the case of success, some Apple APIs record garbage values to error parameters (if non-NULL), then judging the error values will lead to false negative values and crashes.

 

Singleton pattern
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, as its style guide is primarily for print and online readability.

E.g:

self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers: productIdentifiers];
A long line of code should be split into two lines of code, with the next line separated by two spaces.

self.productsRequest = [[SKProductsRequest alloc]
  initWithProductIdentifiers: productIdentifiers];
 

Xcode project
Physical files should be synchronized with Xcode project files to avoid file expansion. The creation of any Xcode group should be reflected in the file of the file system. The code is not only grouped by type, but also by function, which makes the code more clear.

If possible, turn on "Treat Warnings as Errors" in the 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 standards do not meet your taste, you can check other coding standards:

Robots & Pencils
New York Times
Google
GitHub
Adium
Sam Soffes
CocoaDevCentral
Luke Redpath
Marcus Zarra
Reprinted-Objective-C coding specifications


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.