OC代码规范

命名

Preferred :

UIColor *myColor = [UIColor whiteColor];

Not Preferred :

UIColor *myColour = [UIColor whiteColor];

代码组织

使用#pragma mark - 将生命周期、分类方法和代理方法分块标注管理

#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 {}

#pragma mark -  lazy

空格

  • 使用2个空格不要使用Tab键
  • 方法和其他后的大括弧在第一行开始在新的一行结束。
    Preferred:
if (user.isHappy) {
  //Do something
} else {
  //Do something else
}

Not Preferred:

if (user.isHappy)
{
    //Do something
}
else {
    //Do something else
}
  • 在方法中的参数中间添加一个空格方便阅读。
  • 优先使用自动生成,但是如果需要的话可以在实现文件中添加@ synthesize 和 @dynamic。
  • 调用方法时尽量避免方法中冒号对齐。当方法中包含3个以上的参数,使用冒号对齐会增加方法的可读性。但是,当方法中包含block时Xcode 的自动对齐会让代码看起来不容易分辨。
    Preferred:
// blocks are easily readable
[UIView animateWithDuration:1.0 animations:^{
  // something
} completion:^(BOOL finished) {
  // something
}];

Not Preferred:

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

注释

所有的注释必须保持最新或者删除,避免块注释。

命名

尽量保持苹果的命名方式,长的,描述性和变量名都很好。
Preferred:

UIButton *settingsButton;

Not Preferred:

UIButton *setBut;

对于类名和常量名一般使用三字母前缀,在coreData 实体名称可以省略。常量一般遵循驼峰命名方式,使用相关类名最为前缀。
Preferred:

static NSTimeInterval const RWTTutorialViewControllerNavigationFadeAnimationDuration = 0.3;

Not Preferred:

static NSTimeInterval const fadetime = 1.7;

属性命名应该遵循首字母小写的驼峰原则。尽量使用自动生成而非手动。
Preferred:

@property (strong, nonatomic) NSString *descriptiveVariableName;

Not Preferred:

id varnm;

下划线

在初始化的时候,实例变量使用下划线。局部变量不要使用下划线。

方法

在(+/-)符号后添加一个空格,关键词应该对参数有简单的描述。
关键字and的使用不建议使用在多参数的方法名中。

Preferred:

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

Not Preferred:

-(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.

变量

应该使用可描述的变量名称。单字符变量名除了在for循环中使用其他情况不宜使用。
*号应该跟在变量前,NSString text not NSString text;
尽量使用私有属性代替实例变量。
Preferred:

@interface RWTTutorial : NSObject
@property (strong, nonatomic) NSString *tutorialName;
@end

Not Preferred:

@interface RWTTutorial : NSObject {
  NSString *tutorialName;
}

属性

Preferred:

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

Not Preferred:

@property (nonatomic, weak) IBOutlet UIView *containerView;
@property (nonatomic) NSString *tutorialName;

字符串属性推荐使用copy不建议使用strong。
Preferred:

@property (copy, nonatomic) NSString *tutorialName;

Not Preferred:

@property (strong, nonatomic) NSString *tutorialName;

点语法

Preferred:

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

Not Preferred:

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

字面量

NSString, NSDictionary, NSArray, and NSNumber中尽量使用不可变的值。不要在NSArray 和NSDictionary中添加nil值会引起崩溃。
Preferred :

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

Not Preferred:

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

常量

常量应该是静态的常量,不应该是#define 除非作为宏使用。
Perferred:

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

Not Perferred:

#define CompanyName @"RayWenderlich.com"#define thumbnailHeight 2

枚举类型

For Example:

typedef NS_ENUM(NSInteger, RWTLeftMenuTopItemType) {
  RWTLeftMenuTopItemMain,
  RWTLeftMenuTopItemShows,
  RWTLeftMenuTopItemSchedule
};

你可以明确值的分配

typedef NS_ENUM(NSInteger, RWTGlobalConstants) {
  RWTPinSizeMin = 1,
  RWTPinSizeMax = 5,
  RWTPinCountMin = 100,
  RWTPinCountMax = 500,
};

Not Preferred:

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

case 状态

当在switch中使用枚举类型,default是不需要的。

RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;

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

私有属性

私有属性应该在类的实现文件中的类扩展(匿名分类)中声明,命名分类(比如RWTPrivate或private)应该从不使用除非是扩展其他类。匿名分类应该通过使用+Private.h文件的命名规则暴露给测试。

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

布尔类型

Preferred:

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

Not Preferred:

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

如果BOOL属性的名字是一个形容词,属性就能忽略"is"前缀,但要指定get访问器的惯用名称。

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

条件语句

  • 后面要加大括号
    Preferred:
if (!error) {
  return success;
}

Not Preferred:

if (!error)
  return success;

or

if (!error)  return success;

三目运算符

Preferred:

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

Not Preferred:

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

初始化方法

  • 返回类型是instancetype不是返回id。确保编译器正确判断推断结果。
- (instancetype)init {
  self = [super init];
  if (self) {
    // ...
  }
  return self;
}

类构造方法

要求同上

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

CGRect 方法

  • 访问x,y,width或者height时使用CGGeometry来访问。

Preferred:

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

Not Preferred:

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

Preferred:

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

  //Do something important
}

Not Preferred:

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

错误处理

判断返回值而不是错误变量。
Preferred:

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

Not Preferred:

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

单例模式

  • 使用线程安全方式创建实例。
+ (instancetype)sharedInstance {
  static id sharedInstance = nil;

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

  return sharedInstance;
}

换行符

一行代码太长的话可以使用换行符,换成两行。

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

down

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

  • 少用++ -- 运算符
  • 规范只是建议不要拘泥
  • 对于文章的大部分内容还是认同的,但是对于方法名(+/-)符号后添加空格,就个人而言感觉意义并不大。

参考文章

你可能感兴趣的:(OC代码规范)