代码规范[iOS]

 

一、文件系统

  • 总则
    1. 文件的物理路径和逻辑路经保持统一
    2. 每个业务文件夹下都是MVC大结构
    3. 如果有支持性的VC,这个VC写在和View、Model平行的文件夹Vendor文件夹里面
    4. 公用的文件放在最外面
  • 文件命名
    1. 文件夹及文件首字母大写,符合驼峰命名规范
    2. 业务类不需要前缀(PT、HDF,PT是用户维护通用的前缀),如果是公用的非业务层需要加前缀,依据作用范围使用PT或者HDF作为前缀
    3. 数据Model以Model结尾
    4. 业务Model以Manager、Handler、Helper等结尾
    5. 宏文件以Macro结尾
  • 文件顺序
    1. 业务文件夹下依次是大ViewController、Model、View
    2. View文件夹里面顺序是按照页面布局自上向下罗列,如果单个区域view嵌套多可以建一个文件
  • 资源文件
    1. 图片文件都放在 images.xcassets里
    2. 文件结构
      1. 一级目录:医生品牌
      2. 二级目录:点评、服务星(业务)
      3. RTF文本文档放在业务文件夹最上面的层,打开业务文件夹就能看到
    3. 命名
      1. 都以“yspp_”开头
      2. 二级前缀依据图片大小和用途分4个二级前缀yspp_btn_、yspp_icon_、yspp_image_、yspp_screen_  (全屏的图)。

文件结构:

代码规范[iOS]

资源文件结构:

代码规范[iOS]

 

二、代码结构

  • 总则
    1. 声明文件 ( .h 文件)中不能声明实例变量
    2. 实现文件 ( .m 文件)中不声明属性
    3. #import 相关
      1. #import 都写在.m文件里,  .h文件用@class 引用。(.h  只是声明)
      2. #import不能有重复和没有用到的
      3. #import做小的分区分区,分别是:1.自己的View、Model类、2.其他有交互的类、3.工具、类目等
    4. 所有方法名都小写,有前缀的,需把前缀小写加下杠线。(如HDFActionSheet, hdf_actionsheetDidSelected...)
    5. 方法命名不留and   以一个流利的英文句子为基准
    6. 如果方法参数有集合类型的,用泛型标记

      - (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0)__TVOS_PROHIBITED; // supercedes -tableView:titleForDeleteConfirmationButtonForRowAtIndexPath: if return value is non-nil
  • 声明文件 ( .h 文件)  
    1. 顺序(自上向下)
      • 1.#import
      • 2. 枚举
      • 3. 宏
      • 4. 常量
      • 5. delegate声明
      • 6. 属性
      • 7. 方法
      • 8. delegate实现
    2. 属性
      • .h 属性不声明可变对象,可变对象放在 .m实例变量里声明,如果外面需要读取,封装个getter方法,返回不可变对象。
        • @interface DoctorHonoursNetwork : NSObject

          - (void)addItem:(NSObject *)a;

          - (NSArray *)mArray;
        • @interface DoctorHonoursNetwork ()

          {

              NSMutableArray *_mArray;

          }
      • 除“)”左边,声明语句每个单词或逗号后面都加空格,(顺序:内存管理语义-原子性-读写属性)  @property (nonatomic, assign)  NSString *doctorId;
      • 属性是不可变对象都用Copy属性。
      • 可变的属性(Mutable)需要原子操作(atomic)
      • 属性的注释推荐使用方式:/**注释内容*/,这样写在点语法时可以直接展示注释
    3. 方法做分区
      • 如果共公方法多的话做小的功能分区。
    4. delegate
      • 在@interface之前声明,在@end之后实现
      • 方法名都以类名开头(小写),并且自身作为必传参数传回 (- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;)
        • - (void) viewDidDisplay:(UIView *)selfView;

          - (void) view(UIView *)selfView didDisplay;   (不正确的写法)
      • 每个方法必须传回自身
      • delegate必须是weak,避免循环引用
  • 实现文件( .m 文件)  
    1. 实例变量
      • 只在 .m的延展里声明实例变量  (    @interface NSObject ()    )
      • 命名都以 “_”开头
      • 直接用实例变量赋值,如果被赋值对象是NSString、NSArray ,且赋值对象是可变的类,用copy方法赋值。
    2. 生命周期方法结构
      • #pragma mark - life cycle
        • dealloc 最上面
        • 初始化方法
        • 按照页面展现生命周期写 (willAppear、didAppear、willDisappear、DidDisappear)
      • #pragma mark - delegates
        • #pragma mark -- delegate1   (注意第二层中间是两个杠)
        • #pragma mark -- delegate2
      • #pragma mark - event response
        • 方法名以Action结尾 如:backAction、rightItemAction、handleAlertAction
      • #pragma mark - public methods
        • .h中声明的方法
      • #pragma mark - private methods
        • 命名以p_开头  如:p_methodA
        • 延展里声明一下
        • #pragma mark -- UI
      • #pragma mark - getter/setter
        • getter 省略get
        • BOOL类型的 前面加is   (isShowed)
      • #pragma mark - network methods

声明文件:

代码规范[iOS]

实现文件:( Part 1)

代码规范[iOS]

实现文件:( Part 2)

代码规范[iOS]


三、常量  宏

    1. 命名
      • 通用的宏常量和宏函数都大写,单词中间用“_”
      • 私用的宏方法用”__“(两个下杠线开头)全部小写
      • 公有的加YSPP_前缀
      • 私有的确保唯一性,以类名开头,避免覆盖定义
      • 宏函数参数必须用括号括起来(宏只是文本替换)
    2. 文件
      1. 如果该业务的宏比较多,需要单独建文件,以Macro结尾。放在最大作用域*文件夹下面。
  • 常量
    1. 命名
      • 通用的以  FOUNDATION_EXTERN 开头(FOUNDATION_EXTERN NSString * constCommentNotification )
      • 私用的不需要 FOUNDATION_EXTERN  需要加 static 关键字
      • 通用的需要加类名确保唯一性
      • 都以”k"开头
    2. 对象
      • 通用的定义在.h里 ,赋值写在 .m里
        • .h FOUNDATION_EXTERN NSString * const kCommentNotification;
        • .m NSString * const kCommentNotification = @"CommentNotification";
      • 私有的写在.m里
        • .m NSString * const kCommentNotification = @"CommentNotification";

四、布局方式  数据持久化

 
  • 布局方式
    • 写页面方式
      • 纯代码
      • Xib
      • StoryBoard(多人开发噩梦)
    • 布局方式
      • 手算布局
      • AutoResizing(已舍弃)
      • AutoLayout
    • 最终确认布局方式两种:
      • 纯代码  ————>  手算布局
      • Xib       ————> AutoLayout (可视化)
  • 数据持久化
    • 写文件
    • 归档
    • NSUserDefault数据库
      • 引导图,一些小数据的存储
      • 命名
        • key命名 kUserDefault_…
        • 输出一个Const文件,专门存储key
      • 维护文档
    • CoreData
    • ANKeyValueCache  缓存对象,可以是多个对象(流草稿、患教草稿、点评草稿)
    • 最终确认两种数据持久化方式
      • NSUserDefault
        • 引导图,一些小数据的存储
        • 命名
          • key命名 kUserDefault_…
          • 输出一个Const文件,专门存储key
        • 维护文档
      • ANKeyValueCache  缓存对象,可以是多个对象(流草稿、患教草稿、点评草稿)

五、网络

 
  • 文件
    1. 在最大的业务文件夹写一个NetworkManager,所有业务网络请求写在这个里面。参见PatientEducationNetwork.h。
    2. 命名以NetworkManager结尾
  • 结构
    1. 请求方法以每个页面为纬度分区,#pragma mark -
    2. .h  和.m  方法顺序一样
  • 方法注释
    1. 说明方法用途,和必要参数说明,显而易见的参数如patientId,userId不用注释
    2. 注释方法用途和必要注释参数,各占一行。多个参数写在一行上。
  • 方法命名
    • 都以request或post开头,且是类方法(+方法)
  • 接口定义
    1. 接口名定义用常量,写在  .m里面
    2. 以kAPI_开头的  const指针
    3. NSString *const kAPI_doctoruser_getDoctorRecommendInfo =@"doctoruser_getDoctorRecommendInfo";
  • 成功失败回调都用 HDFNetResponse 作为参数。
  • 失败处理
    1. 除非产品特殊要求,失败都应该有提示 [SVProgressHUDshowErrorWithStatus:ERROR_MSG_NONETWORK];
    2. 如果是大WebView页面需要做失败处理点击重新加载的页面(HDFEmptyView)
    3. 如果是列表页,如果数据源是空的需要处理处理点击重新加载的页面,数据源不为空只给提示ERROR_MSG_NONETWORK

文件:

代码规范[iOS]


六、类目、延展

  • category 类目
    1. 命名
      • 类目命名:主类名+大写字母开头的,能概括这个类目意义的单词  (NSString+SizeToFit)
      • 方法命名:类目名+功能名,防止多个类目使用定义功能相同且命名相同方法,互相覆盖
    2. 当一个过于臃肿的大类中的方法可以根据功能类型分组,则将每一组做成一个类目
    3. 一个功能类目对应一个文件,一个类目就是一组相同功能类型的方法簇,不要在一个文件中写多个不同功能类目方法
    4. 一般情况下,不允许在类目中覆盖现有类中的方法,只在类目中扩展新方法
    5. 不允许在类目中定义属性,若有这种需求,定义在主类里,或采用继承解决。(不要用关联对象,不是苹果提倡的做法)
  • extension 延展
    1. 类延展只写在主类的.m文件中,不允许新建文件
    2. 将私有方法原型写在延展中,对外隐藏。
    3. 延展中建议只定义私有实例变量,不定义属性

七、内存、线程

  • 内存泄漏相关
    1. 循环引用类内存泄漏
      • 禁止在成员集合变量中添加成员变量 (例:[_dataArray  addObject: _button1])
      • 设置代理时使用weak指针
      • 使用block时,会出现两种循环引用,如果出现循环引用,在block中使用block的持有者时需要使用weak引用
      • NSTimer如果设置了重复执行模式,则需要在dealloc中进行invalidate;或者使用block类型的NSTimer
    2. 申请了不释放类内存泄漏
      • 代码中使用了通知中心,add了几个,就需要在dealloc方法中对应remove掉几个
      • 使用桥接将Foundation对象转为CoreFoundation对象时,说明此对象脱离ARC管理,需手动调CFRelease释放
      • 代码中使用了GCD队列,需要自己手动释放
      • 自定义GCD队列group,需要自己手动释放
    3. 控制内存峰值
      • 做tableView的时候,使用reuse机制,否则只要tableView不释放,越滑动占用内存越大
      • 如果在循环中有内存操作,则在循环中嵌套autoreleasePool块
  • 线程安全,并发数控制
    1. 总述:线程控制简单的情况下,优先使用GCD,因为GCD用法最简单,抽象层级最低,效率最高;线程控制复杂情况下使用NSOperation,其他的pthread和NSPthread都禁止使用;少用自定义派发队列。
    2. 线程安全
      • 常规写法:

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT), 0), ^{     

                     //可并行执行的处理

                      dispatch_async(dispatch_get_main_queue(), ^{

                          //只能在主线程执行的处理

                      });

        });
      • 单例全部使用dispatch_once来写,目前最可靠的保证单例创建代码不可重入的方式。
      • 增删改临界区数据的操作需同步,使用dispatch_sync来做,调用dispatch_sync方法自动给临界区数据加锁。
      • 读临界区数据不需同步,可以异步提高效率
      • 使用dispatch_barriers实现读写锁(异步读,同步写)
      • 自定义DispatchQueue的名称使用应用程序ID逆序域名(dispatch_queue_create(“newPatient.haodf.com”, NULL))
      • 使用dispatch_group时,添加到group中的派发任务使用相同派发的队列(效率低)
      • dispatch_sync的第一个参数禁止传入当前所在队列(死锁)
    3. 并发数控制:
      • 建议使用 GCD配合 Dispatch Semaphore ,本质上就是个带计数的锁
      • 使用maxConcurrentOperationCount,本质上也是个带计数的锁
      • 平时客户端编程,并发数控制在3个以下
      • 同类型操作可以使用GCD开启多线程,使用Dispatch Semaphore 控制最大并发数,创建Dispatch Semaphore时,将锁计数设置为3,保证线程数<=3;

        例:不同类型操作,调用一次dispatch_async就会增加一个线程,如果同一个时间片内并发线程有可能超过3个,就将线程加入dispatch_group,等待dispatch_group执行结束后,再执行第四条线程,保证线程数<=3;

八、其他

  • 埋点
    1. 命名  UM_YSPP_…….
    2. 文件  MobClickEvent.h,写在最下面  分区
    3. 方式
      • Click        [MobClick event:UM_DOCTOR_SERVICESTAR_CODEPAGE_RULES];
      • 页面   
        • - (void) viewWillAppear:(BOOL)animated {

           [MobClick beginLogPageView:UM_DOCTOR_SERVICESTAR_PREVIEWPAGE];

          [MobClick event:UM_DOCTOR_SERVICESTAR_PREVIEWPAGE];

          }
        • - (void) viewWillDisappear:(BOOL)animated {

          [MobClick endLogPageView:UM_DOCTOR_SERVICESTAR_PREVIEWPAGE];

          }
  • 工程文件、证书
    • 除修改证书、引用文件/库、提测修改版本号/build号、重构ARC代码,不允许修改工程文件。
  • AppDelegate
    • 推送
      • 代码
        • 都在AppDelegate  didReceiveRemoteNotification 处理
        • 分激活状态和未激活状态
        • [UIAlertView showWithTitle:@"温馨提示" message:[[userInfo objectForKey:@"aps"]objectForKey:@"alert"] cancelButtonTitle:@"查看详情" otherButtonTitles:@[@"取消"] tapBlock:^(UIAlertView *alertView, NSInteger buttonIndex) { 

                    //处理通知相关
          }];
      • 数据格式
        • aps是公用参数
        • module是大业务
        • cm是子业务
    • app跳转(URL Scheme)

      医生版 患者版
      微信   wx8afb167c8108d3a9 好大夫患者      haodfpappscheme
      QQ     QQ41D0E0C0 支付                 hdfPatientAlixPay
      微博   wb3026699592 微博                 weiboOAuth
      好大夫患者   haodfappscheme 微信                 wxc7dfdd26c004598c
      好大夫医生   doctorappscheme QQ                   QQ06027529
        QQ空间            tencent100824361

九、版本控制、上线相关

  • 版本控制
    • 一些引导图版本号,只在当前版本出来,用户跳着升级不出来。
    • 数据版本号,考虑数据的有效版本。
  • 上线
    • 如果是打上线包需要改的地方 需要加    #warning 上线
    • 上线前确认:
      • 搜索 #warning 上线 修改需要改的地方
      • 医生版
        • 注释掉所有环境宏
      • 患者版
        • 确认HDFNetworkManager 的 self.productReleasing = YES;


十、附录1(公共库)

序号
功能
对应库文件
备注
1
数据解析                  
MJExtension
 
2
网络        
HDFNet
 
3
弹窗提示              
SVProgressView                       
 
4
上拉下拉刷新
MJRefresh
 
5
用户信息
HDFUserManager
 
6
缓存
ANKeyValueCache
 
7
网络图片
SDWebImage
 
8
大图预览              
PTImageShowViewController
 
9
蒙层引导图          
AppGuideABS
注意版本控制
10
分享
医生版:PTShareSheet
患者版:YMSharedManager.h
 
11
sheet
HDFActionSheet
 
12
语音识别
科大讯飞  iFly
 
13
语音识别输入框
XunfeiTextView
 
14
录音 播放    
HDFVoiceRecorder
 

十一、附录2(公共类目)

序号
功能
对应文件
备注
1

NSArray相关扩展API

NSArray+HDFArray NSArray的排序/JSON互转/是否包含String
2

NSData相关扩展API

NSData+HDFData

NSDate+Addition

String和二进制互转+各种加密算法
3 日期相关扩展 NSDate+HDFDate 所有和年月日星期,闰年等有关的日期操作
4 NSDictionary相关扩展API NSDictionary+HDFDictionary NSDictionary和JSON互转,安全获取键值对
5 文件相关扩展 NSFileManager+HDFFileManager 检验文件是否存在、是否超时、判断文件大小
6 可变数组相关扩展API NSMutableArray+HDFMutableArray 可返回成功/失败状态的交换,移除,插入
7 可变字典相关扩展API NSMutableDictionary+HDFMutableDictionary 带空值检测,可安全的添加对象,网络请求参数,安全存储
8 常用的基类扩展API NSObject+HDFObject

1、获取类名 2、获取文本宽高 3、角度弧度互转 4、随机数 5、对象JSON互转 

6、判断是否安装某应用 7、判断是否能打开某个Itunes应用的链接 8、app跳转

9、打开应用在App Store上的链接 10、移除所有值为null的key-value

9 NSString相关扩展API NSString+HDFString 1、加密 2、断言 3、URL包装 4、过滤HTML标签 5、前缀后缀 6、获取文件路径 7、获取沙盒路径 8、判断是否包含字符串 9、匹配非表情符号的正则表达式
10 定时器相关扩展 NSTimer+HDFTimer 1、block版本定时器(防内存泄露) 2、启动,暂停
11 偏好设置扩展 NSUserDefaults+HDFUserDefaults 更加安全的方式读写UserDefaults
12 ActionSheet扩展 UIActionSheet+HDFActionSheet block回调方式
13 弹窗扩展 UIAlertView+HDFAlertView 1、block回调方式 2、所有样式的弹窗构造方法
14

UIColor相关扩展API

UIColor+HDFHYBColor 1、根据颜色生成图片 2、根据同一颜色生成不同透明度颜色
15 UIControl扩展API UIControl+HDFControl 按钮各种点击状态回调,值改变(segment)回调
16 设备相关扩展API UIDevice+HDFDevice 获取所有设备相关属性
17 手势相关扩展API UIGestureRecognizer+HDFGesture 手势扩展API,block方式回调
18

快速设置UILabel的attributedText属性的扩展API

UILabel+HYBAttributedCategory

快速设置UILabel的attributedText属性的API

19 导航条相关扩展API UINavigationBar+HDFNavigationBarTransluent

快速设置导航条的各种属性

20 UITextView相关扩展API UITextView+HDFTextView 设置UITextView的占位提示语
21 UIView相关扩展API

UIView+HDFView

UIView+Frame

快速获取UIView宽高位置等布局属性
22 各种系统控件的简洁创建配置 UIKitMaker 各种系统控件的简洁创建配置
23 计算文字高度

NSString+ParagrapshStyleSize

NSString+ParagraphSzie

使用attribute方式计算文字高度
24

快速由xib文件创建UITableViewCell

UITableViewCell+InitCell 只适用于xib画出来的cell
25 富文本 NSMutableAttributedString+LBAttributeString Attribute方式制作富文本
26 UITableViewController扩展 UIViewController+MessageRightBarButtonItem 带右上角未读标志的控制器
27 UITabbarItem扩展 UITabBarItem+CustomBadge 带未读标志的tabbarItem
28 UIImage扩展1 UIImage+Extend 1、获得带颜色图片 2、缩放图片
29 UIImage扩展2 UIImage+Blur 1、图片模糊效果 2、屏幕快照
30 计算文字size和高度 NSString+sizeWithFont 计算文字size和高度(boundingRectWithSize方式)
31 快速创建图片button UIButton+image 快速创建图片button

十二、附录3(公共控件)

序号
功能
对应文件
备注
1 空数据页面 PTEmptyDataView  
2 定位功能 PTLocation  
3 底部弹出菜单 HDFActionSheet  
4 循环滚动banner SDCycleScrollView  
5 横向滚动视图 HorizonTableView  
6 进度条 HUDProgressView  
7 自定义tabbar(不可滚动) HDFPageIndexView  
8 自定义tabbar(可滚动) PTTabbar  
9 上下级联段选标签+控制器(类似网易新闻) PTTabbarControllerFacade(PTTabbar+PTTabbarController)  
10 本地草稿 ANKeyValue  
 
上一篇:'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)'


下一篇:GIL锁,线程池