iOS编码规范

2018-08-01  本文已影响0人  JakeyChen

总体命名规则

头文件

变量

变量尽量以描述性的方式来命名。单个字符的变量命名应该尽量避免,除了在for()循环。
星号表示变量是指针。例如, <font color=#FF69B4>NSString *text </font>既不是 <font color=#FF69B4>NSString* text</font> 也不是 <font color=#FF69B4>NSString * text</font>,除了一些特殊情况下常量。

  1. 类成员变量

    类中所有成员变量以属性的方式提供,不要使用其他类型的变量声明。

    通过使用'back'属性(_variable,变量名前面有下划线)直接访问实例变量应该尽量避免,除了在初始化方法 <font color=#FF69B4>(init, initWithCoder:</font>, 等…), <font color=#FF69B4>dealloc</font> 方法和自定义的<font color=#FF69B4>setters</font>和<font color=#FF69B4>getters</font>。如果要使用成员变量,必须以下划线'_'开头,如 NSString *_name。局部变量不应该包含下划线

    应该:

    @interface Test : NSObject
    @property (nonatomic, strong) NSString *name;
    @end
    

    不应该:

    @interface Test : NSObject {
     NSString *_name;
        }
    
  2. 私有属性应该声明在类的.m中,只有需要外部使用的变量才声明在.h中。

  3. 所有属性特性应该显式地列出来,有助于新手阅读代码。属性特性的顺序应该是atomicity、storage。

    应该:

    @property (nonatomic, strong) NSString *name;
    

    不应该:

    @property (nonatomic) NSString *testName;
    
  4. 属性是指针类型的集合时,格式如下:
    @property (nonatomic, strong) NSArray <Item *>*array;

  5. 属性是delegate时,声明成weak,防止循环引用,格式如下:
    @property(nonatomic, weak) id<UIScrollViewDelegate> delegate;

常量

常量应该使用static来声明而不是使用#define,除非显式地使用宏。

应该:

static NSString * const kJMAboutViewController = @"JMAboutViewController";
static CGFloat const kRowHeight = 50.0;

不应该:

#define kJMAboutViewController @"JMAboutViewController"
#define kRowHeight 2

布尔值

Objective-C使用的是BOOL值,对应的是YES和NO。true和false是bool类型,Objective-C不要使用。

既然nil解析成NO,所以没有必要在条件语句比较。不要拿某样东西直接与YES比较。

应该:

if (someObject) {
}
if (![anotherObject boolValue]) {
}

不应该:

if (someObject == nil) {}
if ([anotherObject boolValue] == NO) {}
if (isAwesome == YES) {} // Never do this.
if (isAwesome == true) {} // Never do this.

如果BOOL属性的名字是一个形容词,属性就能忽略"is"前缀,但要指定get访问器的惯用名称。例如:
@property (assign, nonatomic, getter=isEditable) BOOL editable;

枚举型

普通枚举型

typedef NS_ENUM(NSInteger,JMTypeTest){
 kJMTypeA = 0, // 注释
 kJMTypeB = 1, // 注释
 kJMTypeC = 2, // 注释
 kJMTypeD = 3  // 注释
};

可按位或

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

字面值

NSString, NSDictionary, NSArray, 和 NSNumber的字面值应该在创建这些类的不可变实例时被使用。请特别注意nil值不能传入NSArray和NSDictionary字面值,因为这样会导致crash。

应该:

NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];
NSDictionary *productManagers = @{@"iPhone": @"Kate", @"iPad": @"Kamal", @"Mobile Web": @"Bill"};
NSNumber *shouldUseLiterals = @YES;
NSNumber *buildingStreetNumber = @10018;

不应该:

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];

操作符

一元操作符不带空格,多元运算符要带空格隔开。

  1. 逗号后面都要跟随一个空格。

    NSArray *array = @[1, 2, 3, 4];

  2. 二元操作符,如+, -, *, /,>, <, =, ==, ->, <<, >>等。

    a + b = c;
    a > b;
    a == b;
    a << 2;
    Object -> c;
    
  3. 三元操作符 Non-boolean的变量与某东西比较,加上括号()会提高可读性。如果被比较的变量是boolean类型,那么就不需要括号。

    应该:

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

    不应该:

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

集合类型

NSArray *array = @[ 
    @"This",
    @"is",
    @"an", 
    @"array"
];

NSDictionary *dictionary = @{
    NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12], 
    NSForegroundColorAttributeName : fontColor 
};

系统保留字

应该

if (a == 1) {
    NSLog(@"test1");
} else if (b == 2) {
    NSLog(@"test2");
} else {
    NSLog(@"test3");
}
switch (condition) {
  case 1:
    // ...
    break;
  case 2: {
    // ...
    // Multi-line example using braces
  }
    break;
  case 3:
    // ...
    break;
  default: 
    // ...
    break;
}

不应该

if(a==1){
    NSLog(@"test1");
}else if(b==2){
    NSLog(@"test2");
}else{
    NSLog(@"test3");
}

if条件语句

函数声明

应该

- (UIView *)initWithTitle:(NSString *)title backgroundColor:(UIColor *)color;

不应该

-(UIView *)initWithTitle:(NSString *)title withBackgroundColor: (UIColor*) color;

函数实现

- (void)popBack {
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                       URLString:(NSString *)URLString
                                      parameters:(id)parameters
                                  uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
                                downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
                                         success:(void (^)(NSURLSessionDataTask *, id))success
                                         failure:(void (^)(NSURLSessionDataTask *, NSError *))failure

.m文件整理

init方法

Init方法应该遵循Apple生成代码模板的命名规则。返回类型应该使用instancetype而不是id。

- (instancetype)init {
  self = [super init];
  if (self) {
    // ...
  }
  return self;
}

类构造方法

当类构造方法被使用时,它应该返回类型是instancetype而不是id。这样确保编译器正确地推断结果类型。

@interface Airplane
+ (instancetype)airplaneWithType:(RWTAirplaneType)type;
@end

回调方法

函数调用的可知性,回调时被调用者要知道其调用者,方便信息的传递,所以建议在回调方法第一个参数中加上调用者。除非只有一个名为sender的参数。

如:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)windowShouldClose:(id)sender;

CGRect函数

当访问CGRect里的x, y, width, 或 height时,应该使用CGGeometry函数而不是直接通过结构体来访问。引用Apple的CGGeometry:

应该:

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);

不应该:

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 };

单例模式

单例对象应该使用线程安全模式来创建共享实例。

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

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

  return sharedInstance;
}

Block

__weak typeof(manager)wManager = manager;
    
[manager POST:url parameters:reqDic progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [wManager invalidateSessionCancelingTasks:false];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [wManager invalidateSessionCancelingTasks:false];
    }];
    

图片资源命名

图片资源命名方式,以 模块 + 功能 为组织形式,如果相同功能有多个,比如表情,则再加编号。

如:

tabbar_item_1.png
tabbar_item_2.png

maitoutiao_topicon_1.png
maitoutiao_topicon_2.png

注释

警告⚠️

尽量减少⚠️的产生,能修改的要及时修改。

上一篇 下一篇

猜你喜欢

热点阅读