oc代码规范之规范定义

oc的代码规范大抵都是一样的,重要的是执行。正常review两三个版本就可以在团队内部形成统一的风格。当然这些规范也可能随着成员认知的变化而发生变化,没必要教条。

语言规范

  • [强制]命名规范

    • [强制]命名约定通 准则:清晰、 一致性。
      1. 清晰:命名应该既清晰 简短,但拒绝为 追求简短 丧失清晰性,拒绝为 简洁进 随意缩写。
      2. 一致性:命名含义应该具有前后,全局的一致性,同个功能也应该使 同个名称。
    • [强制]尽量不用缩写,除以下已经长期使用形成共识的内容。
      命名 说明
      alloc allocate
      dealloc dealloc
      info information
      init initialize
      min minimum
      max maximum
      temp temporary
      int integer
      msg message
    • [强制]禁止使用系统前缀开头,以防止冲突,原则上两字母前缀都是系统保留前缀,尽量使用三个字符最为前缀。
    • [强制]方法名、参数名、成员变量、局部变量都采小写字符开头,驼峰命名法。
    • [强制]如果方法代表执行某个动作,应该以动词开头。
    • [强制]如果方法返回某个属性,应该直接以属性作为方法名,只有当间接返回对象或返回多个对象时,可以使 get。
    • [建议]同一个类的一系列相关方法命名应该有一致性,入参更多的方法应该在入参更少的方法名后面增加新关键字。
    如:
      - (instancetype)initWithURL:(NSURL *)URL;
      - (instancetype)initWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy
    
    • [建议]动词前可以根据具体情况增加 can, should, will等 情态动词使方法更明确。
    • [强制]不要使用一到两个字符的名称。
    • [建议]delegate方法名称的开头应标识出发送消息的对象所属的类。
    如:
      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    
  • 常量定义

    • [强制]使用NS_ENUM声明枚举类型,枚举项以枚举类型为前缀。
    typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
        UIViewAnimationCurveEaseInOut,
        UIViewAnimationCurveEaseIn,
        UIViewAnimationCurveEaseOut,
        UIViewAnimationCurveLinear,
    };
    
    • [强制]使用NS_OPTIONS声明位移枚举常 ,位移枚举常量可以组合使用。
    typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
        UIViewAutoresizingNone = 0,
        UIViewAutoresizingFlexibleLeftMargin = 1 << 0, 
        UIViewAutoresizingFlexibleWidth = 1 << 1,
        UIViewAutoresizingFlexibleRightMargin = 1 << 2, 
        UIViewAutoresizingFlexibleTopMargin =1<<3, 
    }
    
    • [强制]通常情况下, 不要使用宏创建数值和字符串常量,使 static声明变量,并在头文件中以extern的方式暴露给外部。
    如:
    .m  :
    NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem" 
    .h  :
    extern NSString * const AFNetworkingReachabilityNotificationStatusItem;
    
    • [强制]Notification消息使用全局的NSString对象进行标识,名称按如下方式组合:
         [Name of assoicated class] + [Did|Will] + [Unique part of name] + Notification
      如:
         UIApplicationDidEnterBackgroundNotification
    
  • 类定义

    • [强制]使用property代替成员变量。
    • [建议]需要时在property声明自定义getter或setter。
    @property(nonatomic, getter=isHidden) BOOL hidden;
    
    • [强制]需要对外公开的声明放在.h中,其他都放在.m中。
    • [强制]+ (void)initialize必须判断class类型,因为任何继承类也会执行父类的initialize。
    + (void)initialize {
          if (self == [ClassName class]) {
            // ... do the initialization ...
          }
    }
    
    • [建议]使用nonnull, nullable, __kindof等 来修饰入参、返回值、属性。
    • [建议]使 designated initializer指定初始化方法:
      1. designated initializer提供所有参数,secondary initializer提供一些默认参数来调用designated initializer。
      2. 一个类最好有一个designated初始化方法,其他初始化方法应该调用该方法。
      3. 继承时应该注意:
        a. 子类designated应该调用直接父类的designated initializer方法。
        b. 重载直接父类的designated initializer,调用你的designated initializer。
        c. 可以 __attribute((unavailable)) 标记不可用的父类designated initializer。
    如:
    - (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil NS_DESIGNATED_INITIALIZER;
    - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
    
  • 注释

    • [建议]使 Xcode自带工具插入默认格式,Option+Command+/即可自动插入。
    • [建议]复杂难懂的逻辑添加注释。
    • [建议]公共类头文件中暴露的方法都应该添加注释。
  • 代码组织

    • [建议] 一个类功能较多时,可以使用Category的方式进行功能划分,这些Category可以放在同一个文件中。
    • [建议]使 #pragma marks - 进行方法分组。
    • [强制]合理使用group或folder组织工程结构,文件folder结构和工程group结构要对应。
    • [建议]过期方法不要直接删除,先标记为deprecated。
    • [建议]函数内嵌套不要太深,大括号嵌套大括号不要超过三层。
  • Switch

    • [强制]Switch一定要实现default,防止case侧漏处理。
    • [强制]每个case必须写break。
    • [强制]每个case不管多少, 用大括号括起来。

工程规范

  • CocoaPods使用规范

    • [强制]Podfile.lock文件必须提交到git版本控制,以保证版本可回溯。
    • [强制]Podfile中必须指定三方库的版本或SHA值,以防意外更新。
    • [强制]区分pod install和pod update的使用场景,默认使用pod install。
    • [强制]开发pod库在提交repo前,本地进行lint校验。
  • Git使用规范

    • [强制]本地分支提交前,使 git pull --rebase将本地分支进行rebase。
    • [强制]使用gitlab上的用户名和邮件,不要有多套用户名和邮件。
       $ git config --global user.name "输入你的名字"
       $ git config --global user.email abc@example.com
    

最佳实践

  • 多线程

    • [强制]创建线程必须命名。
    • [强制]单例创建要使用dispatch_once确保线程安全。
    • [强制]在多线程环境下使用lazy load方式加载变量有crash风险,必须加锁保护
    • [强制]performSelector:withObject:afterDelay:要在有Runloop的线程调用,否则无效。
    • [强制]禁止随意创建常驻线程,除非在整个App 命周期有必要且有任务运行。
    • [强制]Notification在哪个线程中post,就在哪个线程中被转发,如果有UI操作,注意dispatch到主线程。
    • [强制]禁止在主线程进 文件IO操作,必须异步处理。
    • [强制]剪贴板读取必须放在异步线程处理。
  • 内存管理

    • [建议]慎重使用单例,避免造成不必要的常驻内存。
    • [强制]Delegate需要使用weak引用。
    • [强制]使用block访问self时,使用weakify和strongify避免Retain Cycle。
    • [强制]strong引用子对象,weak引用父对象,基础类型使 assign,NSString、NSArray、block使用copy。
    • [强制]在dealloc 法中remove observer。
    • [强制]指定repeat参数是YES的timer,必须在合适的时机调用invalidate方法。
    • [强制]在init和dealloc中除非类属性外,禁止使用self访问属性,只允许通过成员变量直接访问。
      1. 在init和dealloc截断,self是一个不完整的对象。
      2. 子类可以重写accessor方法,在某些情况下可能导致异常。
    • [强制]在使用到UIScrollView,UITableView,UICollectionView的class中,需要在dealloc中将 delegate,dataSource置为nil。
    • [强制]禁止一次性申请超过10MB的内存。
  • 集合

    • [强制]插入对象和使用literals需要做 非空判断。
    • [强制]注意线程安全问题,必要时加锁,保障线程安全。
    • [强制]遍历可变集合时,先copy,再遍历临时变量。
    • [强制]禁止mutable对象作为入参传递,禁止返回mutable对象。
    • [建议]使用NSCache 而不是NSMutableDictionary作为缓存。
    • [建议]容器使用泛型指定对象类型。
           NSArray <NSString *> *stringArray;
      
  • 字符串

    • [建议]使用keypath时,尽量使用NSStringFromSelector(@selector()),防止某个属性被删除后没有编译器检查。
    • [建议]取substring时考虑emoji字符问题,防止截到中间crash。

    (参见:http://blog.csdn.net/liu1347508335/article/details/52484507

    • [强制]专锁专用,一个lock对象只负责 一个任务。
    • [建议]根据不同使用场景和性能要求,使用不同类型的锁。
    • [强制]使用锁return前,记得unlock,如果在try catch中,记得在finally中unlock。
  • IO

    • [建议]经常被读取的文件做好内存缓存,减少IO开销。
    • [强制] 文件存储路径遵守以下规则:
      1. Documents 录:存储用户数据,该路径可以通过iTunes存取,会被iTunes备份。
      2. Library 录:
        a. Preferences目录:包含应用程序偏好设置文件。
        b. Caches目录:存放缓存信息, 不会被备份。
        c. tmp目录:存放临时文件,不会被备份。
        d. 创建其他目录:放置不希望被用户看到的数据,会被备份。
  • Category

    • [强制]category方法加上 定义前缀,防止冲突覆盖。
    • [强制]禁 category 法覆盖系统方法。

相关的pdf

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354