preface

Please let me know if there is something wrong or you need to add.

Proper code specifications and standards do not eliminate the creativity and elegance of code content, but limit excessive personalization, and do things together in a universally accepted and uniform way, thereby increasing productivity and reducing communication costs. Code between the lines flowing is the blood of the software, quality improvement is as little as possible to step on the pit, put an end to the repetition of stepping on the pit, effectively improve the stability of the system, code quality.

Code specifications may seem to limit your freedom and play, but they are indirectly helping you become better.

According to the constraint strength, the specification is tentatively agreed into two levels, namely [must] and [recommended].

(1) Naming conventions


Tips: All naming should follow three basic principles: "Clarity," "consistency," and "Don't refer to yourself."Copy the code
1. Common naming conventions
  • Clarity: A good name should be self-describing.
Is exemple: removeObject:, [string stringByReplacingOccurrencesOfString: @ "1" withString: @ "2"] counterexamples: remove: (not clear, want to delete what?) , string. Replace (" 1 ", "2"), is the "1" to replace "2" or "2" will be replaced with "1"? Replace the first "1" with a "2" or replace all "1" with a "2")Copy the code
  • [Must] Consistency: Naming should be consistent with context and even globally. Variables of the same type or function should be named in the same or similar way.
Example: /* count is defined in NSDictionary, NSArray, and NSSet classes. And the count attribute in all three collection classes represents the same thing, that is, the number of objects in the collection. */ @property (readonly) NSUInteger count;Copy the code
  • Self-reference must be prohibited: names do not refer to themselves. Except for notifications, mask constants, and so on (usually enumerated values that can be operated on bitwise).
Positive example: NSString Negative example: NSStringObjectCopy the code
  • [Must] avoid excessive abbreviations, do not create abbreviations (such as “button” to BTN); Except for international acronyms such as ATM and GPS. (Just because you know what an acronym means doesn’t mean everyone else will, and creating a comparison table for abbreviations just adds complexity.)
Example: destinationSelection, setBackgroundColor, destSel, setBgColorCopy the code
  • [Must] eliminate meaningless pinyin, except international common names or place names (alibaba, Taobao, Hangzhou).
Counter example: DaZhePromotion(discount)Copy the code
  • Naming should be as clear and concise as possible, or if both are not possible, clarity is the priority.
Positive: insertObject:atIndex: negative: insert:at: unclear, insert what? What does at stand for?Copy the code
  • Racial slurs in any language should be avoided in both code and comments.
Positive example: secondary Negative example: slaveCopy the code
  • [Mandatory] Global names such as class names, protocol names, function names, constant names, and enumeration names need to be prefixed. The prefixes must contain at least two characters in uppercase.
Tips: The system reserves the right to use any two characters as prefixes, including but not limited to NS, UI, CG, CF, CA, WK, MK, CI, NC. We generated a large number of plasmids for mouse and mouse toll-like receptor receptors. We generated a large number of plasmids for mouse and mouse receptorsCopy the code
  • [Must] Global names such as class names, protocol names, function names, constant names, and enumeration names follow the camel’s hump with uppercase names, except for special names whose first word is HTTP.

  • [Must] Some non-global names, such as method names and attribute names, are named in a lower-case hump, except for the special words whose first word is HTTP.

  • Member variables must start with _.

Example: NSString *_nameString;Copy the code
  • When naming constants or variables, try to put the type noun at the end of the word to make it more recognizable.
Positive example: nameLabel Negative example: name(is name a string or something?)Copy the code
  • [Suggestion] If a module, interface, class, or method uses a pattern, name it to reflect the pattern.
Example: OrderFactory, LoginProxyCopy the code
  • [Suggestion] Local temporary variable names can be prefixed with identifiers.
Example: T_label, t_stringCopy the code
2. Class naming conventions
  • [Must] The class name naming style consists of “prefix + class name + class type”. The prefix must be greater than 2 characters and all uppercase; The name of the class should be named in an uppercase hump. The name of the class should express the function of the class. Use the full name of the class type. Do not use abbreviations (VC instead of viewController, cell instead of TableViewCell). The naming method is the same as the name.
Example: WXYZ_LoginViewControler WXYZ_ indicates the prefix, Login indicates that the class is associated with logins, and ViewController indicates that the class is a View controller rather than a View.Copy the code
3. Method naming conventions
  • [Must] All methods are prohibited from starting with new.

  • [Must] All methods are prohibited from starting with _.

Tips: The system identifies some private methods with the beginning _Copy the code
  • [Must] Internal private methods need to have prefixes that remain unique (for example, p_).
Tips: Prefixing private methods has two benefits: 1. Increased recognition and code readability. 2. Avoid accidentally overwriting system/framework private methods of the same name with your methods.Copy the code
  • If the method returns a property value from the receiver, use the property name as the method name directly.
- (CGSize)cellSize; Counter example: - (CGSize)getCellSize;Copy the code
  • If the method indirectly returns one or more values, then it can be named “getXXX”, which only works if it returns multiple data items.
Is: - (void)getCachedResponseForDataTask:(NSURLSessionDataTask *)dataTask completionHandler:(void (^) (NSCachedURLResponse *  __nullable cachedResponse))completionHandler;Copy the code
  • Keyword must be added before each parameter of the method.
- (void)sendAction: SEL)aSelector toObject:(ID)anObject forAllCells:(BOOL) Flag; Counter example: - (void)sendAction: SEL)aSelector :(ID)anObject :(BOOL) Flag;Copy the code
  • [Suggestion] The word before the parameter can describe the meaning of the parameter.
Example: - (id)viewWithTag:(NSInteger)aTag; Counter example: - (id)taggedView:(int)aTag;Copy the code
  • Do not use “and” to connect to the receiver attribute. Although “and” reads well, this can cause problems as the number of parameters you create increases.
- (int)runModalForDirectory:(NSString *) Path file:(NSString *) Name types:(NSArray *)fileTypes; Counter example: - (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;Copy the code
  • If methods describe two separate actions, they can be joined using “and”.
Positive example: - (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;Copy the code
4. Protocol Naming convention
  • [Must] Method names in Protocol start with the name of the object that triggered the message, omit the class name prefix and start with a lowercase letter. This rule can be ignored if it is not associated with any classes.
- (BOOL)tableView shouldSelectRow (NSTableView *)tableView shouldSelectRow (int)row; - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;Copy the code
  • [Mandatory] Unless the Protocol method has only one argument, the colon must follow the class name.
- (BOOL)tableView shouldSelectRow (NSTableView *)tableView shouldSelectRow (int)row; - (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;Copy the code
5. Category naming conventions
  • Class names must also be prefixed as class names.
Positive example: UIView (YYAdd) Negative example: UIView (Add)Copy the code
  • All method names declared in a class must be prefixed.

  • [Suggestion] Do not declare attributes in a Category. If possible, declare them in the main class.

Tips: Although it is technically possible to declare attributes in a category, doing so requires great care as it is prone to memory or other problems and is difficult to troubleshoot.Copy the code
  • If a class is complex, it is recommended to use the classification organization code (refer to the system’s UIView).
6. Notification naming convention
  • The naming style of Notification consists of “class name prefix” + “Notification event name “+ “Notification”.
Is exemple: UIApplicationDidBecomeActiveNotification UIApplication said the notice which belongs to the class object, DidBecomeActive said the notice, Notification said it is a notice.Copy the code
  • If a class declares the delegate property, the delegate object of that class should generally receive most notification messages via the delegate method implemented.
Tips: for example, applicationDidBecomeActive: proxy method and NSApplicationDidBecomeActiveNotification notice (it also conforms to the fundamental principles of naming conventions "consistency").Copy the code
7. Constant naming conventions
  • If the constant is limited to a “compilation unit”, it is usually prefixed with a lowercase letter k. If the constant is globally visible, it is usually prefixed with the class name and is named in the same way as methods and variables.
Const CGFloat kScreenWidth ([UIScreen mainScreen].bound.size.width)Copy the code
8. Exception naming conventions
  • The command specification is the same as for Notification. Change the suffix to “Exception”.
9. File naming conventions
  • [Must] All file names are lowercase.

  • [Must] use _ linking words.

  • [Must] name style: “module _ attribute description”.

Is: [email protected]Copy the code

(2) Coding specification


1. General coding specifications
  • [Must] When using frameworks like CF(Core Foundation), or when using notifications and KVO on systems below iOS10, remember to release or remove notifications and listens in the dealloc method.

  • [Must] disallow passing self in the dealloc method. If self is retained, it will be released multiple times in the next runloop cycle, resulting in crash.

Example: - (void)dealloc {[self unsafeMethod:self]; }Copy the code
  • Obsolete methods or classes should be prohibited and new methods or classes should be learned and used in time.

  • The reading of the clipboard must be done in a child thread because the user may copy a large amount of data content on the iPhone or Mac.

  • [Must] {} must follow if, else, for, while, case, etc., unless followed by a simple return statement, such as if (XXX) return; .

  • When a method may return early, care needs to be taken to release the object to avoid memory leaks.

Counterexample: CFArrayRef arrayRef = (__bridge CFArrayRef)array; if (x == YES) return; CFRelease(arrayRef); If x is equal to YES then the arrayRef object will have a memory leak.Copy the code
  • When using @try to handle exceptions, care should be taken to release the object to avoid memory leaks.
Counterexample: @try {CFArrayRef arrayRef = (__bridge CFArrayRef)array; Do some thing... CFRelease(arrayRef); } @catch (NSException *exception) {} If do some thing... If there is an exception then arrayRef will have a memory leak.Copy the code
  • To declare constants, use const type declarations. #define macros are not allowed.
Macro definitions are simple substitutions, lack of compilation checks, and may cause problems such as overflow or data errors at run time. 2. Macro definitions lack types, making it difficult to write documented use cases. 3. Macro definitions can be accidentally replaced. 4. Macro definition cannot be commented. #define kTime @"10" if (@[].count > 0) {#define kTime @"20"} NSLog(@"time = %@", kTime); The code in if in the example above will not execute, but the compiler will also replace kTime with @"20"Copy the code
  • [Suggestion] When writing public methods, use inline or global functions rather than macro definitions.
UIKIT_STATIC_INLINE NSString * kNSStringFromInteger(NSInteger a) {return [NSString stringWithFormat:@"%zd", a]; } #define kNSStringFromInteger(a) [NSString stringWithFormat:@"%zd", a]Copy the code
  • [Must] UITableView uses self-sizing to implement unequal height cells, Please in tableView: cellForRowAtIndexPath: proxy approach to cell set data rather than the tableView: willDisplayCell: forRowAtIndexPath: proxy method in the data set.

  • Use lazy loading only when necessary.

Tips: Lazy loading can only be used in the following three situations: 1. Object creation depends on other objects. 2. Objects may or may not be used 3. Object creation comparison consumes performanceCopy the code
  • [Must] There must be no Spaces on either side of the unitary operator.
Positive example: I ++, ++ I, negative example: I ++, ++ ICopy the code
  • [Must] There must be only one space on the left and right sides of the binocular and triadic operators.
Positive example: 1+2 Negative example: 1+2Copy the code
  • [Must] Use four Spaces to indent. To use Tab characters, set one Tab to four Spaces.

  • Do not call the synchronize method when storing data with NSUserDefaults, because the system will save the data locally when appropriate (even in extreme cases such as a rollback).

  • Objects added to the collection should be immutable, or their hash code immutable after addition.

NSMutableSet *sets = [NSMutableSet set]; NSMutableString *string1 = [NSMutableString stringWithString:@"1"]; [sets addObject:string1]; [sets addObject:@"12"]; [string1 appendString:@"2"]; When [string1 appendString:@"2"] completes, sets will contain two @"12" objects, which is incorrect.Copy the code
  • [Must] You must use CGRectGet to get the various values of the Frame, not through the Frame. Is obtained by using the.
Tips: CGRect t_frame = CGRectMake(-10, -10, -10, -10); When a view's frame is set to T_frame, its coordinates are implicitly converted to CGRectMake(-20, -20, 10, 10); All values obtained by t_frame. will be wrong, and CGRectGet will automatically handle these hidden conversions for you. Positive examples: CGRectGetWidth(frame), CGRectGetMinX(frame), and CGRectGetMaxX(frame) Frame.size.width, frame.origin. X, frame.size.width + frame.originCopy the code
  • [Mandatory] The maximum number of characters in a line cannot exceed 150. If the number exceeds the limit, follow the following rules for line feeding:
1. Indent the second line by 4 Spaces compared to the first line, and do not indent any more from the third line. 2. The operator is newline with the rest of the text. 3. The method call dot is wrapped with the rest of the text. Is: - (void)setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options progress:(nullable YYWebImageProgressBlock)progress ransform:(nullable YYWebImageTransformBlock)transform completion:(nullable YYWebImageCompletionBlock)completion;Copy the code
  • [Suggestion] Use copy as much as possible for immutable objects. If you want to override the set method that uses copy, call the copy method.

  • [Suggestion] Use NSUserDefaults to store small and important information, instead of storing it locally frequently. It is stored locally at the right time, which avoids frequent write operations, and it can be stored locally in extreme cases (such as when a program fails).

  • [Suggestion] Use mutable collections with caution in multithreaded environments. If necessary, use lock or GCD synchronous threads for protection, or copy mutable collections as immutable objects before accessing them (immutable collection objects are thread-safe).

  • [Suggestion] Do not declare member variables in header files.

  • [Suggestion] Declare the properties in the header file as read-only as possible. You can declare the properties as readable and writable in the implementation file.

Example: @interface WXYZModel: NSObject @property (nonatomic, readonly) NSString *name; @end @interface WXYZModel () @property (nonatomic, strong) NSString *name; @endCopy the code
  • [Suggestion] The lazy loading method should only perform the operations that need to be initialized. There should be no other unnecessary logical code.

  • [Suggestion] Do not use one class to maintain the contents of multiple classes. For example, one constant class maintains all constant classes.

Tips: Large and complete classes, clutter, use the search function to locate the specific location, not conducive to understanding and maintenance. Positive example: Cache-related constant classes are stored under CacheCosts, and system config-related constant classes are stored under SystemConfigConsts.Copy the code
  • [Suggestion] If the braces are empty, write {} concisely.

  • [Suggestion] It is not necessary to add extra space to align the equal signs above and below the code.

Int a1 = 1; long a2 = 3; NSString *a3 = @""; Int a1 = 1; long a2 = 3; NSString *a3 = @"";Copy the code
  • [Suggestion] Use if return instead of if else. If nesting should not exceed 5 levels.
If (x == 1) { return; } if (x == 2) {... return; } if (x == 1) {... } else if (x == 2) {... }Copy the code
  • [Suggestion] Avoid using the inverse logic operator, because it is not easy to understand quickly.
If (array == nil) {... } Example: if (! Array) {... }Copy the code
  • [Suggestion] If many protocols are used, encapsulate them into a single header file if necessary. This not only reduces compilation time, but also avoids circular references.

  • [Suggestion] When using the Switch enumeration, try to list all enumeration types instead of default. In this way, a warning message will be displayed if the Switch does not handle the enumeration type next time.

  • [Suggestion] Use literal syntax to create objects as much as possible, and use less equivalent methods.

Tips: OC NSArray, NSString, NSDictionay, and NSNumber all have literal grammars for them: @[], @"", @{}, @(); Using them has the following advantages: 1. They are easy to read and improve code readability and maintainability. 2. ArrayWithObjects: if you create an array or dictionary with literals, it will throw an exception if the elements are nil. ArrayWithObjects: if you create an array or dictionary with literals, it will throw an exception if the elements are nil. Cons: 1. Objects created using literals are immutable by default. To create mutable objects, you need to perform a mutableCopy operation. 2. No subclass support. If you create a subclass of NSString, @"" will not return the subclass object you want.Copy the code
  • Minimize references to other headers in your header files, use @class forward declarations as much as possible, and ask yourself if you have to do this every time you introduce another header.

  • [Suggestion] Weak rather than strong is recommended for UI controls.

2. Class coding specification
  • If an initialization method of the superclass does not apply to a subclass, the subclass must override the method of the superclass and either resolve the problem or throw an exception.

  • [Suggestion] Try to use functions instead of class methods to improve efficiency.

  • [Suggestion] Try not to use the load method, if you must use complex logic that cannot be implemented inside the method to block the thread.

  • [Suggestion] Minimize inheritance. Inheritance of a class should not exceed three levels. If necessary, you can consider using classes or protocols to replace inheritance.

  • Extract stable, public variables or methods into the parent class. Subclasses try to maintain only features and functions that the parent class does not have.

3. Method coding specification
  • [Must] disallow use inside initialization methods such as init, getters, setters, dealloc, or other special places. Syntax access attributes.
Tips: Used when an inheritance relationship exists. Syntax access actually calls the methods of the subclass due to polymorphism, which can cause some weird problems if the subclass is not initialized or the subclass is freed.Copy the code
  • Method arguments must be defined and passed with a space after the comma.
Method (A1, A2, a3);Copy the code
  • [Suggestion] The number of lines of a single method cannot exceed 80, except comments, open and close braces, blank lines, and carriage returns.

  • [Suggestion] Use it within the implementation file as much as possible. Syntax accesses attributes instead of using _ to access member variables directly.

4. Block coding specification
  • [Must] Calls to Block must be nulled.
Tips: Simple blocks can be nulled using the ternary operator, such as! self.block ? : self.block();Copy the code
  • Beware of circular references when using external variables inside blocks.
You don't have to use self inside a Block to make a circular reference. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { WXYZ_TitleTableViewCell * cell =...... cell.refreshTableViewBlock = ^{ [tableView reloadData]; }; return cell; } 2. The use of weak inside a Block depends on whether there is a direct or indirect reference between the Block itself and the weak object. If there is no mutual reference, weak is not used. Weak type (self) weakSelf = self; weak type (self) weakSelf = self; weak type (self) weakSelf = self; weak type (self) weakSelf = self; weak type (self) weakSelf = self; weak type (self) weakSelf = self; weak type (self) weakSelf = self. cell.refreshTableViewBlock = ^{ __strong typeof(weakSelf) strongSelf = weakSelf; if (strongSelf ! = nil) { strongSelf->_name = @"name"; }}; If you take (strongSelf! = nil) then it might crash.Copy the code
5. Notify coding specification
  • [Must] When sending notifications, use userInfo to pass values instead of Object.

  • The notification center sends requests synchronously, so don’t do complicated calculations on the notification method, especially if it’s on the main thread. If you want to send asynchronous notifications you can use NSNotificationQueue.

  • [Suggestion] In the project, notice can be used without notice as far as possible. Although notice is flexible and powerful, if it is abused, the quality of the project will decline, and it is difficult to troubleshoot when problems occur.

6. Comment on coding specifications
  • Rather than agonize over comments, think of names; A good name should be self-explanatory. If the name explains what it does and the method has no side effects or caveat, don’t use the comment. Comments should help others understand the method’s use and precautions more quickly. If there are any concerns about the method, be sure to include them in the comments.

  • The comments need to be synchronized when the method implementation is changed.

  • [Must] The comments should not be too long, but should be simple and easy to read and understand. After the method is modified, the comments should be modified in time.

  • There must be only one space between the double slash and the content of the comment.

  • [Must] be careful about commenting code. There are two possibilities for code to be commented: 1) the code logic will be restored later; 2) Never use; For the first case, corresponding comments should be added. If there is no annotation information, it is difficult to know the annotation motivation, and the latter is recommended to delete directly. If necessary, you can access the history code through the code repository.

  • [Must] When using special annotation tags, please specify the tag person and the tag time, and pay attention to the timely processing of these tags.

/** * @brief * @author */ // FIXME: there is a bug, need to be fixed - (void)testFunction;Copy the code
Example: // This is the example comment. Note that there is a space after the double slash - (void)testFunction;Copy the code
  • Don’t comment bad code, refactor it.
Tips: Comments should not beautify bad code. Before attempting to use comments, consider whether you can adjust the structure, name, and so on to eliminate the need for comments.Copy the code

(3) Engineering structure specifications


  • Locally used constants and static variables must be declared before @interface.

  • [Must] @property Declarations of the same type are put together. Declarations of different types are separated by two lines of space.

Is: @interface MineViewController () <UITableViewDataSource, UITableViewDelegate> @property (nonatomic, weak) UIView *headView; @property (nonatomic, weak) UITableView *tableView; @property (nonatomic, copy) NSArray *dataSourceArray;Copy the code
  • [Must] insert a blank line between different logic, different semantics, different business code to improve readability.
[self createSubviews]; [self createTableview]; [self netRequest];Copy the code
  • Methods must be classified
#pragma mark - LifeCycle - (void)dealloc {} - (void)viewDidLoad {} - (void)viewWillAppear:(BOOL)animated {} #pragma mark - Public // code... #pragma mark-override #pragma mark-override #pragma mark-override #pragma mark-override #pragma mark-override #pragma mark-override #pragma mark-override #pragma mark-delegate #pragma mark-getter /setterCopy the code

Download link

reference


  1. Cocoa Coding Specification
  2. Alibaba Java code specification
  3. 52 Effective ways to Write high-quality iOS and OS X code in Effective Objective-C 2.0
  4. Articles about code specifications published by others on the web