美文网首页
Objective-C编码规范

Objective-C编码规范

作者: Alphts | 来源:发表于2017-01-17 14:06 被阅读51次

    前段时间接手了一个开发三年之久的老项目,三年期间经历了5-6个程序员的开发,整个项目架构比较混乱,代码风格差距很大,也有许多不规范代码,难以Code Review。对于承担这个项目的维护、部分代码重构以及后续产品开发的责任,我拟定了这个迟到了三年之久的项目代码规范,要求所有的iOS同事在之后的开发以及代码的重构过程中以此作为编码规范。此代码规范一直是我自身的代码规范,来源于几年前借鉴 raywenderlich的Objective-C style ,感兴趣的朋友可以去GitHub上自行搜索。

    命名###

    • 变量的命名使用US英语,不可使用拼音代替;
    • 尽可能坚持Apple的命名规则,长的,描述性的方法和变量命名是最好的
      应该:
      UIButton *nextButton;
      UIlabel *nameLabel;
      或者可以使用简介的命名方式:
      UIButton *btn_next;
      UILabel *lb_name;
      切不可随意命名控件:
      UIButton *next;
      UILabel *name;
    • 变量的命名采用驼峰命名法则,并且单词的首字母需要小写
    • 星号表示变量是指针。例如, NSString *text 既不是 NSString* text 也不是 NSString * text,除了一些特殊情况下常量。

    下划线###

    • 当使用属性时,实例变量应该使用self.来访问和改变。这就意味着所有属性将会视觉效果不同,因为它们前面都有self.当然,重写属性的set,get方法中等必须使用下划线的情况下使用下划线.

    代码组织###

    • 使用#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 {}
      
    • 注释: .h文件中必须要有注释,标明属性方法等的含义,.m文件中选择性适当注释业务逻辑。当需要注释时,注释应该用来解释这段特殊代码为什么要这样做。任何被使用的注释都必须保持最新或被删除。

    • 方法之间的间隔
      在方法签名中,应该在方法类型(-/+ 符号)之后有一个空格。在方法各个段之间应该也有一个空格(符合Apple的风格)。在参数之前应该包含一个具有描述性的关键字来描述参数。
      应该:
      - (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;
      不应该:
      -(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.

    • 在方法之间应该有且只有一行,这样有利于在视觉上更清晰和更易于组织。在方法内的空白应该分离功能,但通常都抽离出来成为一个新方法。

    • 缩进使用4个空格,确保在Xcode偏好设置来设置,确保代码对齐。

    • 方法大括号和其他大括号(if/else/switch/while 等.)总是在同一行语句打开但在新行中关闭
      应该:
      if (user.isHappy) {
      //Do something
      } else {
      //Do something else
      }
      不应该:
      if (user.isHappy)
      {
      //Do something
      }
      else {
      //Do something else
      }

    • 应该避免以冒号对齐的方式来调用方法。因为有时方法签名可能有3个以上的冒号和冒号对齐会使代码更加易读。请不要这样做,尽管冒号对齐的方法包含代码块,因为Xcode的对齐方式令它难以辨认。
      应该:
      // blocks are easily readable
      [UIView animateWithDuration:1.0 animations:^{
      // something
      } completion:^(BOOL finished) {
      // something
      }];
      不应该:
      // colon-aligning makes the block indentation hard to read
      [UIView animateWithDuration:1.0
      animations:^{
      // something
      }
      completion:^(BOOL finished) {
      // something
      }];

    变量###

    • 私有变量应该尽可能代替实例变量的使用。尽管使用实例变量是一种有效的方式,但更偏向于使用属性来保持代码一致性。
      应该:
      @interface RWTTutorial : NSObject
      @property (strong, nonatomic) NSString *tutorialName;
      @end
      不应该:
      @interface RWTTutorial : NSObject {
      NSString *tutorialName;
      }

    字面值###

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

    枚举类型###

    • 当使用enum时,推荐使用新的固定基本类型规格,因为它有更强的类型检查和代码补全。现在SDK有一个宏NS_ENUM()来帮助和鼓励你使用固定的基本类型。
      例如:
      typedef NS_ENUM(NSInteger, RWTLeftMenuTopItemType) {
      RWTLeftMenuTopItemMain,
      RWTLeftMenuTopItemShows,
      RWTLeftMenuTopItemSchedule
      };
      或者显式地赋值:
      typedef NS_ENUM(NSInteger, RWTGlobalConstants) {
      RWTPinSizeMin = 1,
      RWTPinSizeMax = 5,
      RWTPinCountMin = 100,
      RWTPinCountMax = 500,
      };
      不应该:
      enum GlobalConstants {
      kMaxPinSize = 5,
      kMaxPinCount = 500,
      };

    条件语句###

    • 只用一行代码,也应该使用大括号包围。一方面,可能发生在if语句里面一行代码被注释了,然后下一行代码不知不觉地成为if语句的一部分。另一方面,这种风格与其他条件语句的风格保持一致,所以更加容易阅读。
      应该:
      if (!error) {
      return success;
      }
      不应该:
      if (!error)
      return success;
      也不应该:
      if (!error) return success;

    黄金路径###

    • 当使用条件语句编码时,不要嵌套if语句,多个返回语句也是OK。
      应该:
      - (void)someMethod {
      if (![someOther boolValue]) {
      return;
      }
      //Do something important
      }
      不应该:
      - (void)someMethod {
      if ([someOther boolValue]) {
      //Do something important
      }
      }

    Xcode工程###

    • 物理文件应该与Xcode工程文件保持同步来避免文件扩张。任何Xcode分组的创建应该在文件系统的文件体现。代码不仅是根据类型来分组,而且还可以根据功能来分组,这样代码更加清晰。

    相关文章

      网友评论

          本文标题:Objective-C编码规范

          本文链接:https://www.haomeiwen.com/subject/lxsmbttx.html