iOS代码规范

作者: 江湖闹士 | 来源:发表于2021-05-29 08:51 被阅读0次

    前言:无规矩不成方圆,项目开发过程中,代码规范看起来是一件不起眼的事,每个接手开发的人用按照自己的一套习惯来操作命名,随着项目壮大,整体看就会感觉很乱,没有章法,让人没有欲望去了解去接手。
    一个好的命名规范:代码应该简洁、易读、易懂,逻辑清晰。
    核心原则:写代码不要炫技,用简单直观符合思维惯性的方式去写代码,降低别人的理解成本。
    那么我们就从iOS常用的类、方法等一一列举。

    一、资源规范

    图片资源

    1、(组件化开发中)各组件图片资源应该放到各自组件assets中,不允许业务新增资源丢到壳工程中
    2、图片资源命名单词小写以下划线拼接如:
    tabbar_mine_select

    二、代码规范

    类的布局

    为了他人阅读你代码容易,请让你写的类按照以下方式进行布局。(⚠️注意:#pragma mark 后面有个" - ")

    #pragma mark - Life Cycle
    #pragma mark - Setup View / Data
    #pragma mark - Observer
    #pragma mark - Notification
    #pragma mark - Event Response
    #pragma mark - Override Methods
    #pragma mark - Delegate
    #pragma mark - Public Methods
    #pragma mark - Private Methods
    #pragma mark - Setter / Getter
    #pragma mark - Network
    

    命名
    1、代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
    2、类名使用 UpperCamelCase(大驼峰命名)风格,必须遵从驼峰形式,专有名词除外:如:UDP。
    3、方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase(小驼峰命名)风格,必须遵从驼峰形式。
    4、一个标识符的命名应该简单好懂,避免使用复杂单词。
    5、viewDidLoad 和 init 方法里面不能把初始化 UI 和数据的代码混在一起,要拆成两个方法。初始化 UI 和 数据的方法放在 #pragma mark - Setup View / Data 里面,而且方法的命名应该避免使用 init、get、set
    开头,建议命名:

    - (void)setupViews;
    - (void)setupUI;
    - (void)createUI;
    - (void)configData;
    - (void)setupData;
    - (void)fetchData;
    

    6、当一个页面要刷新 UI 或者数据时,建议的命名是:

    - (void)updateUI;
    - (void)refreshUI;
    - (void)reloadData;
    - (void)refreshData;
    

    7、方法命名举例: 属性/函数/参数/变量/常量/宏 的命名应该保持清晰+简洁,如果鱼和熊掌不能兼得,那么清晰更重要

    Good:
    insertObject: atIndex:  
    removeObjectAtIndex:
    removeObject: 
    
    Bad:
    insert:at:  不清晰,插入什么?at代表什么?
    remove: 不清楚到底要删什么?
    
    Good:
    - (NSSize)cellSize;
    - (int)runModalForDirectory:(NSString *)path file:(NSString *) name types:(NSArray *)fileTypes;
    - (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag;
    
    Bad:
    - (NSSize)getCellSize;
    - (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;
    - (int)runModalForDirectory:(NSString *)path withFile:(NSString *)name withTypes:(NSArray *)fileTypes;
    - (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;
    

    1、类的命名以公司特定标识开头,比如科瑞有限公司,那么就 KR 开头(下面都用KR做例子)。
    2、类名:类名的命名遵循大驼峰式命名法,类名中可以添加工程的前缀,防止多个子工程出现类名重复的情况。
    3、如果是 Model必须使用 Model 结尾,View 必须是 View结尾,UIViewController VC 结尾,UITableViewController TVC结尾,UICollectionViewController CVC 结尾。
    4、MVVM 中的 ViewModel以Logic 结尾,里面只能放逻辑,不能有任何 UI相关的代码。LogicViewController的数据传递推荐使用代理BlockObserver不可以使用通知。
    5、不要在工具类里面写业务逻辑,工具类就是工具类。
    6、在类的头文件中尽量少引用其他头文件,使用 @class 声明。
    7、创建一个类的时候,里面默认生成的被苹果注释掉的代码,全部删掉。包括-(void)didReceiveMemoryWarning也要删除,平时注掉不用的代码如无特殊原因,一概删除,注掉不删,要写明不能删的原因。
    8、Router协议命名:KR+名称+RouterProtocol KRMineRouterProtocol
    9、【推荐】如果你重写了初始化方法,希望用调用方用你写的构造函数,那么请用:NS_DESIGNED_INITIALIZER
    宏来指定调用方使用哪个初始化方法。如:

    - (instancetype)initWithText:(NSString *)text NS_DESIGNATED_INITIALIZER;
    

    10、【推荐】如果你想让调用方只使用你写构造函数,也可以用 NS_UNAVAILABLE

    屏蔽系统的构造函数。如:

    + (instancetype)new NS_UNAVAILABLE;
    - (instancetype)init NS_UNAVAILABLE;
    - (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
    - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
    

    11、【推荐】如果你提供的方法想弃用掉,发现调用的地方比较多,一下子全改风险大,请用attribute((deprecated("已弃用, 用payWithPayInfo替换")));标明弃用,随着版本迭代逐步替换使用新方法。

    方法

    1、方法名的命名规范遵循小驼峰式命名法
    2、要 区分方法调用和属性访问

    推荐:
    view.backgroundColor = [UIColor orangeColor]; 
    [UIApplication sharedApplication].delegate;
    不推荐:
    [view setBackgroundColor:[UIColor orangeColor]]; 
    UIApplication.sharedApplication.delegate;
    

    3、方法后面的花括号不能换行。
    4、单一职责原则,一个方法只干一件事情。
    5、重载方法的时候,如无特殊情况均需要先调用super的方法。
    6、在方法之间应该有且只有一行。这样有利于在视觉上更清晰。方法内为了视觉清晰,也酌情空行,但不要每写一行就空一行,够一个功能段空一行

    分类

    分类命名要用 " KR"开头,如:UIColor+KRExtensions.h,暴露出来的方法要以 "kr_"开头,如:

    @interface UIColor (KRExtensions)
    - (UIColor *)kr_customColor;
    @end
    

    单利

    1、使用dispatch_once 来生成单例
    2、单例方法命名都应该加上 shared
    如: + (instancetype)defaultManager;
    不知道该怎么给单例方法起名字就用:
    + (instancetype)sharedInstance;
    3、【建议】如果声明了单例请用 NS_UNAVAILABLE 屏蔽掉 init 方法,如:

    - (instancetype)init NS_UNAVAILABLE; 
    + (instancetype)new NS_UNAVAILABLE;
    

    代理

    1、一个类实现了那些代理,要明确的写到.m文件匿名分类的后面。苹果官方的写在前面,自定义的写在后面如:

    @interface KRTopicController () <UITableViewDelegate, UITableViewDataSource, KRTopicHeaderViewDelegate>
    @end
    
    @implementation KRTopicController
    @end
    

    2、不允许这样写 self.tableView.delegate = (id)self;
    这样写的坏处是:当看一个类里面的方法,发现没有地方调用,但这个方法也会走,怀疑是个代理,但看看头文件又没实现这个代理,看代码的人是很恐慌的。
    3、代理一般情况下都是有两个或两个以上参数的,第一个参数返回调用代理的owner,如:

    @class KRTopicHeaderView;
    @protocol KRTopicHeaderViewDelegate <NSObject>
    @optional
    - (void) topicHeaderView:(KRTopicHeaderView *)view tapAvatar:(UIButton *)avatarBtn;
    - (void) topicHeaderView:(KRTopicHeaderView *)view tapCreditScore:(UIButton *)creditScoreBtn;
    @end
    

    变量

    1、变量名的命名规范遵循小驼峰式命名法(方法参数名的命名规则和变量名一致)。
    2、一个变量有且只有一个功能,尽量不要把一个变量用作多种用途
    3、一行声明一个变量,不要一行声明多个变量
    4、少用变量标记,多用方法传值。
    5、强烈建议使用枚举来定义一些变量。
    6、不要使用 floatint 定义基本类型,使用 CGFloatNSInteger
    代替,这样的好处是 32 位的机型 CGFloat 会转为 float,64 位的机型 CGFloat
    会转为double

    属性

    1、变量定义,推荐用属性的方式去声明,不要用全局变量
    全局变量的声明方式是MRC时代的编码风格,现在是ARC时代,不要用。要注意,属性的声明

    @interface KRTopicController { 
        _varxxx; 
    }
    
    // *应该紧挨着变量名。
    @interface KRTopicController () 
    @property (nonatomic, strong) KRTopicHeaderView *headerView;
    @property (nonatomic, strong) KRTopicFooterView *footerView;
    @end
    
    @implementation KRTopicController
    @end
    

    2、public 属性放 .h 文件里面,private 属性放 .m
    文件的匿名分类里面。不要用 _xxx 的写法。
    3、尽量使用不可变对象。包括:
    (1)在头文件中,设置对象属性为readonly
    (2)NSStringNSDictionaryNSArray 使用 copy关键字指定
    (3)字典 使用 NSDictionary,而不是 NSMutableDictionary;数组 使用
    NSArray,而不是 NSMutableArray
    (4)向集合类型中添加元素要添加非空判断。

    常量

    常量定义,如果是给整个项目使用的常量定义为:
    static NSString *const kSimpleString = @"simpleString";
    如果只是给某个类使用的常量,定义为:
    static NSString *const kClassNameConstName = @"ClassNameConstName";
    宏定义和常量在 Xcode里面的显示颜色是不一样的,足以区分。当一个标识符既可以用宏定义又可以用常量的情况下首选常量。原因:常量可以在控制台打印方便调试。

    宏定义

    1、宏定义
    #define kSafeStr(str) (([str isKindOfClass:[NSNull class]] || !str) ? @"" : [NSString stringWithFormat:@"%@", str])
    
    小写k开头然后遵循小驼峰命名法。
    2、宏定义不允许定义字符串、字面值只能用来定义代码段。
    

    枚举

    枚举定义应该使用 OC的声明方式,避免使用C的写法。定义方式如下:
    typedef NS_ENUM(NSInteger, KRInformationType) {
        KRInformationLikeType = 0,// 喜欢
        KRCommentType ,// 评论
        KRMentionType ,// @
        KRSysMsgType // 系统消息
    };
    

    Block

    1、调用block时需要对block判空
    2、block中如果使用了self,block用 @weakify(self); Block 中使用
    @strongify(self);不要自己写 weakstrong

    通知

    除特殊情况下,不允许使用。

    引入第三方代码

    引入第三方代码要注意,必须是在社区有一定知名度,github star数要够多,同一个功能的库找最多的用,必须用pod管理。有一种情况是你要做的功能就是没有知名库,但有别人已经写好的,是可以引用的,但review时会问你原因,review的人要根据他说的情况搜一下,看是不是真的没有知名库可以用。

    注释

    1、注释的作用:一份规范的代码必定不能缺少详尽的注释,注释的目的:方便工作交接和引导新同事熟悉代码 方便自己之后回忆代码逻辑 方便生成文档
    2、注释分为单行注释和多行注释
    (1)对于属性我们使用三杠 /// 进行单行注释,这样 Xcode 代码提示的时候会显示注释内容

    ///用户名
    @property (nonatomic, copy) NSString *userName;
    

    (2)对于特殊行//代码块注释的注释的使用双杠 //

    if(orderType == JYOrderTypeNone){
        //无订单处理        
    }
    

    (3)对于方法我们使用多行注释

    /** 
     * @brief 设置是否处于选中状态
     * @param selected 是否选中 
     * @param animated 是否使用动画效果 
     */ 
     - (void)setSelected:(BOOL)selected animated:(BOOL)animated;
    

    其他

    1、管理缓存使用 NSCache 而不是NSMutableDictionary,好处有一下几点:
    (1)NSCache 是线程安全的,在进行多线程操作时,不需要进行加锁。
    (2)NSCache在系统内存很低时会自动释放对象。
    2、判断nil 或者YES/NO

    正确写法:
    if (someObject){ ... }
    if (!someObject) { ... }
    错误写法:
    if (someObject == YES) { ...}
    if (someObject != nil) { ...}
    if (someObject == YES)容易误写成赋值语句if (someObject = YES)这样在开发的过程中不好被发现。
    

    3、BOOL赋值正确写法:

    Good:
    BOOL isAdult = age > 18;
    
    Bad:
    BOOL isAdult;
    if (age > 18) {
        isAdult = YES;
      } else {
        isAdult = NO;
    }
    

    4、工程名:工程名的命名必须有强烈的导向性,让人看到工程名的第一眼就明白该工程对应哪个项目。如KRUserModule
    工程名字不能出现中文,不允许有空格。 工程名字采用大驼峰式命名法。

    相关文章

      网友评论

        本文标题:iOS代码规范

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