iOS - Summary of Common Programming Specifications

Keywords: xcode Programming Attribute iOS

All specifications for programming languages, if not written here, are in Apple's documentation:

Catalog

Point grammar

Attributes should always be accessed or modified using point grammar, and parentheses are preferred when accessing other instances.

Recommend:

view.backgroundColor = [UIColor orangeColor];

[UIApplication sharedApplication].delegate;

Opposition:

[view setBackgroundColor:[UIColor orangeColor]];

UIApplication.sharedApplication.delegate;

spacing

  • An indentation uses four spaces, or tab indentation.
  • Method braces and other braces (if/else/switch/while, etc.) always start on the same line as the declaration and end on the new line.

Recommend:

if (user.isHappy) {
    // Do something
} else {
    // Do something else
}
  • There should be just one blank line between methods, which helps with visual clarity and code organization. Blank separation should be used between functional blocks in a method, but often a new method should be created.

Conditional judgement

The main part of conditional judgment should always be enclosed in braces to prevent errors, even if it does not need braces (for example, it only needs one line);

These errors include adding a second line (code) and expecting it to be part of the if statement;

Another, more dangerous, is that when a line in an IF statement is commented out, the next line becomes inadvertently part of the if statement.

In addition, this style is more in line with all other criteria and therefore easier to check.

Recommend:

if (!error) {
    return success;
}

Opposition:

if (!error)
    return success;

or

if (!error) return success;

ternary operator

The trinomial operator,?, is used only when it can increase code clarity or cleanliness. Single conditions should be given priority to use. It is usually easier to understand if statements when there are multiple conditions, or to reconstruct them into instance variables.

Recommend:

result = a > b ? x : y;

Opposition:

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

error handling

When referring to a method that returns an error parameter, it should be for the return value, not the error variable.

Recommend:

NSError *error;
if (![self trySomethingWithError:&error]) {
    // Handling errors
}

Opposition:

NSError *error;
[self trySomethingWithError:&error];
if (error) {
    // Handling errors
}

Some Apple API s write garbage values to the wrong parameters (if not null) in case of success, so targeting the wrong variables can cause false results (and subsequent crashes).

Method

In the method signature, there should be a space after the -/+ symbol. There should also be a space between method fragments.

Recommend:

- (void)setExampleText:(NSString *)text image:(UIImage *)image;

variable

Variable names should be as descriptive as possible. Except for the for() loop, you should avoid using single-letter variable names in other cases.

An asterisk indicates that the pointer belongs to a variable, such as: NSString *text should not be written as NSString *text or NSString *text.
Except for constants.

Define attributes as much as possible instead of using instance variables directly.

In addition to initialization methods (init, initWithCoder:, etc.), dealloc methods and custom setters and getters, direct access to instance variables should be avoided.

Recommend:

@interface Model: NSObject

@property(nonatomic,copy)NSString *name;

@end

Opposition:

@interface Model : NSObject {
    NSString *headline;
}
// * Number should be associated with instance variables
@property(nonatomic,copy)NSString * name;
@property(nonatomic,copy)NSString* name;

Variable qualifier

When it comes to Introduced in ARC When a variable qualifier is used,
Qualifiers (_strong, _weak, _unsafe_unretained, _autoreleasing) should be between asterisks and variable names, such as NSString* _weak text.

name

Follow Apple's naming conventions as much as possible, especially those involving Memory management rules,(NARC .

Long and descriptive method names and variable names are good.

Recommend:

UIButton *settingsButton;

Opposition:

UIButton *setBut; // Vague

Attributes and local variables should use hump nomenclature with lowercase initials.

For consistency, instance variables should be named using the hump nomenclature, with the initials lowercase and prefixed with underlines. This is consistent with the instance variables automatically synthesized by LLVM.
If LLVM can synthesize variables automatically, let it synthesize automatically.

Recommend:

@synthesize descriptiveVariableName = _descriptiveVariableName;

Opposition:

id varnm;

Notes

Annotations should be used to explain why specific code does something when needed. Any comments used must be kept up to date or deleted.

Usually you should avoid a large block of comments, and the code should try to be your own document, requiring only a few lines of explanation. This does not apply to annotations used to generate documents.

init and dealloc

The dealloc method should be placed at the top of the implementation file, just behind the @synthesize and @dynamic statements. In any class, init should be placed directly under the dealloc method.

The init method should be structured like this:

- (instancetype)init {
    self = [super init]; // Or call the specified initialization method
    if (self) {
        // Custom initialization
    }

    return self;
}

Literal

Literals should be used whenever immutable instances of NSString, NSDictionary, NSArray, and NSNumber classes are created. Note that nil values cannot be passed to NSArray and NSDictionary literals, which can cause crashes.

Recommend:

NSArray *names = @[@"Marry", @"Maya", @"Vivian", @"Alex", @"Eric", @"Cherry"];
NSDictionary *products = @{@"name" : @"iPhone 7", @"date" : @"2016-11-11", @"size" : @"5.5"};
NSNumber *isHappyToday = @YES;
NSNumber *phoneNumber = @110120119;

Opposition:

NSArray *names = [NSArray arrayWithObjects:@"Marry", @"Maya", @"Vivian", @"Alex", @"Eric", @"Cherry", nil];
NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"iPhone 7", @"name", @"2016-11-11", @"date", @"5.5", @"size", nil];
NSNumber *isHappyToday = [NSNumber numberWithBool:YES];
NSNumber *phoneNumber = [NSNumber numberWithInteger:10018];

CGRect function

When accessing x, y, width, height of a CGRect, you should use CGGeometry function Instead of directly accessing structure members. Apple's CG Geometry reference says:

All functions described in this reference that take CGRect data structures as inputs implicitly standardize those rectangles before calculating their results. For this reason, your applications should avoid directly reading and writing the data stored in the CGRect data structure. Instead, use the functions described here to manipulate rectangles and to retrieve their characteristics.

All function descriptions in CGRect can be used as input specifications before rectangular data results are calculated by CGRect implicit data method. For this reason, your application should avoid directly reading and writing data or data structures in CGRect. Instead, use the functions described here to manipulate rectangles and retrieve their features.

Recommend:

CGRect frame = self.view.frame;

CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);

Opposition:

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;

constant

Constants are preferred as inline strings literals or numbers, because constants can be easily reused and quickly changed without the need for lookups and substitutions. Constants should be declared as static constants rather than # define, unless they are explicitly used as macros.

Recommend:

static NSString * const reusableCellIdentifier = @"Identifier";

static const CGFloat cellHeight = 50.0;

Opposition:

#define reusableCellIdentifier @"Identifier"

#define cellHeight 20.0

Enumeration type

When using enum, a new basic type specification is recommended, because it has stronger type checking and code completion capabilities. Now the SDK contains a macro to encourage the use of the new base type - NS_ENUM()

Recommend:

typedef NS_ENUM(NSInteger, XMButtonsType) {
    XMButtonsTypeAdd,
    XMButtonsTypeDecline
};

Private attributes

Private attributes should be declared in Extension of class implementation files.

Recommend:

@interface XMViewController ()

@property (nonatomic, copy) NSString *privateName;
@property (nonatomic, assign) NSInteger count;
@property (nonatomic, strong) NSMutableArray *dataSource;

@end

Picture naming

Picture names should be uniformly named to maintain the integrity of the organization. They should be named a hump string describing their purpose, followed by a prefix-free name (if any) for a custom class or attribute, followed by a further description of color and/or display location, and finally their status.

Recommend:

  • RefreshBarButton Item/RefreshBarButton Item@2x and RefreshBarButton Item Selected/RefreshBarButton ItemSelected@2x

Pictures used for similar purposes in the picture catalogue should be grouped into their respective groups.

Boer

Because nil resolves to NO, there is no need to compare it in terms. Never compare directly with YES, because YES is defined as 1 and BOOL can be up to 8 bits.

This makes the entire document more consistent and visual clarity.

Recommend:

if (!someObject) {
}

Opposition:

if (someObject == nil) {
}

For BOOL, there are two uses:

if (isTrue)
if (![someObject boolValue])

Opposition:

if ([someObject boolValue] == NO)
if (isTrue == YES) // Don't do that.

If a BOOL attribute name is an adjective, the attribute can omit the "is" prefix, but specify a common name for the get accessor, such as:

@property (assign, getter=isEditable) BOOL editable;

Single case

Singleton objects should use thread-safe patterns to create shared instances. (GCD is recommended to create singletons)

+ (instancetype)sharedInstance {
    static id sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });

    return sharedInstance;
}

Import

If there are more than one import statement, the statements are grouped. Annotations for each group are optional.

// Frameworks
#import <UIKit/UIKit.h>

// ViewController
#import "XMViewController.h"

// Models
#import "XMUser.h"

// Views
#import "XMButton.h"
#import "XMUserView.h"

Xcode project

To avoid file clutter, physical files should be kept in sync with Xcode project files. Any group created by Xcode must have a corresponding mapping on the file system. For clarity, code should be grouped not only by type, but also by function.

Examples: (by type)

Posted by pentinat on Mon, 01 Apr 2019 07:15:32 -0700