iOS编码规范v0.4

该文档规范了iOS编码时的相关注意事项,iOS开发人员必须认真阅读、理解和严格遵守该规范。其目的在于促进开发团队的代码规范化和成员的编码风格,同时提高团队的整体代码质量,降低后期代码维护成本等。


编码规范总体要求:

  • 切图在有2倍图和3倍图时,不允许再添加1倍图。
  • Git提交、合并到主分支必须要有详细备注说明,最终合并代码中不允许出现测试代码。
  • 所属开发模块不允许再出现编译警告。
  • 新界面开发必须采用自动布局(xib或者Masonry)。
  • Git建议一个需求一个分支,一个Bug一个分支。
  • 分支合并,当APP全局配置存在冲突时,全部以主分支为准。如有变更请详细说明原因。
  • 业务参数和业务逻辑必须添加相应注释。无相关注释禁止合并代码。
  • 所负责业务需求,必须进行自测和兼容性测试。
  • 及时删除不需要的资源文件和类文件。
  • 不仅要实现功能,更要时刻关注性能。

编码命名规范

要求示例
目录/文件夹1.目录文件夹名称单词首字母大写,不可使用中文。
2. Xcode目录引用:创建物理目录,添加引用,不直接创建虚拟目录。
3.目录划分按照功能模块或者职责。
4.新建文件夹注意target选择
Hotel
Controller
ViewModel
1.类名单词首字母大写,缩写词字母全部大写,遵循驼峰法命名。
2.视图控制器的子类应该添加后缀“ViewController”或者“Controller”,视图的子类则应该添加具体视图的后缀,XxxView,XxxButton,XxxLabel
3.不同业务模块应选取合适的前缀,避免命名出现冲突。
4.尽量使用能够反映类功能的名词短语
5.新建类请注意target选择。
AppDelegate.h
URLController.h
HotelHomeViewController.h
HotelHomeTableView.h
SettingView
SettingButton
Category1.Category命名必须为:类名+name.h
2.通过分类名称可知道该Category的功能
3.Category中的自定义方法尽量添加前缀,避免方法覆盖,例如sd_前缀
NSString+MD5.h


– (nullable NSURL *)sd_currentImageURL;
方法1.方法使用小写开头的驼峰法命名,每个参数都应该小写开头, 参数类型星号前要有一个空格。- 或者 + 符号后面紧跟一个空格。
2. 减少方法参数个数,如方法参数过多,建议采用Model或集合进行替代。
3.方法名尽量使用能够表明方法目的的动词短语
4.方法参数首字母小写,之后每个单词字母大写
5.方法应添加合理注释
6.方法参数过长,建议换行并以:对齐
+(NSURL *)URLWithString:(NSString *)URLString;

– (void)sd_setImageWithURL:(nullable NSURL *)url
                  forState:(UIControlState)state
                 completed:(nullable SDExternalCompletionBlock)completedBlock;
属性1.属性声明采用nonatomic,为第一个关键字
2.UIKit相关属性声明,须添加具体后缀。例如:historyTableView,deleteOrderButton,nameLabel
3.只读属性添加readonly关键字
4.尽量使用Code Snippet快捷生成
5.小写开头,驼峰命名
6.属性类型与服务器返回类型保持一致。例如:int对应int,string对应NSString
@property (nonatomic, strong, nullable) UIView *backgroundView
变量1.小写字母开头,驼峰命名。
2.添加类型后缀,xxxView,xxxButton
UIView *backgroundView;
常量1.全局宏定义建议添加模块前缀,避免冲突
2.全局常量使用小写k开头的驼峰法
3.局部常量建议添加当前类名为前缀
protocol
delegate
1.@protocol名称须以 类名+Delegate/DataSource.h
2.delegate属性声明使用weak关键字
3.合理使用@optional 和@required
@protocol UITableViewDelegate<NSObject, UIScrollViewDelegate>


@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;
Block1.尽量采用typedef定义block
2.属性中使用copy关键字
3.block须检查是否存在循环引用
4.block中的代码逻辑不宜过长,须考虑是否单独抽离方法
5.block回调时应检查是否为空
枚举1.统一采用OC风格枚举
2.枚举项命名按照枚举名称+xxx形式
3.枚举判断优先采用switch
4.采用NS_ENUM和NS_OPTIONS定义枚举,并指明数据类型。
typedef NS_ENUM(NSInteger, UIViewTintAdjustmentMode) {
    UIViewTintAdjustmentModeAutomatic,
    
    UIViewTintAdjustmentModeNormal,
    UIViewTintAdjustmentModeDimmed,
}
通知名称1.通知名称以小写k开头,Notification结尾
2.通知名称要加具体业务模块名称进行区分,防止通知名称冲突
3.添加具体的注释说明通知发出时机
4.尽量采用全局定义
kHotelOrderUpdateNotification
图片1.采用Assets管理
2.图片目录按照功能模块进行划分
3.名称按照 类型+模块+name或模块+name
4.图片区分target,智能公务之家单独Assets
icon_hotel_arrow
日志统一采用日志中心进行日志打印和日志上报。不允许出现无用的日志。

注释规范:

要求示例
类文件注释1.类文件Xcode会自动添加相关注释
2.作者请使用开发人员姓名全拼或缩写
Created by awnlab on 2019/1/15.
方法注释1.使用Xcode 注释方法,option+command+/
2.方法功能说明,参数说明,返回值说明
3.避免不必要的注释
/**
 重置badge number为0
 */
+(void)resetAppBadgeNumber;
属性/变量注释单行注释采用//或///方式添加注释
多行注释采用/* xxx */   
/**
Xxxxxx
*/
业务Model属性必须添加注释,说明字段含义用途等。重要!
@property(nonatomic) CGPoint           center;      // center is center of frame. animatable
#pragma mark采用pragma mark进行代码功能分块注释。#pragma mark – JPush Delegate
//TODO:尚未完成的逻辑代码建议添加TODO注释,完成之后删除该注释,不允许出现已完成功能后仍存在TODO注释的情况。重要!//TODO: xxxxxx
NSAssert公共API或公共组件建议合理使用断言。
Xcode编译警告所负责模块代码不允许出现Xcode警告,出现警告后应当认真检查是否存在问题,并解决警告。
测试代码最终合并代码不允许存在测试代码。
单元测试编写合理可用的单元测试。
git代码提交与合并每次代码提交、合并到主分支,必须有详细的开发备注描述。

第三方库

  • 尽量减少第三方库的使用,框架导入直接导入根头文件。
  • 非通用工具类第三方库,禁止在PCH或公共头文件中进行引用,应当由具体业务模块自己引用。
  • 第三方库优先采用CocoaPods管理。
  • 核心业务代码中建议尽量减少对第三方库的直接使用。
  • CocoaPods添加新的第三方库后建议使用pod install命令,禁止使用pod update命令,如需更新某个第三库到最新版本,请使用pod update xxxx(注意提前考虑更新后是否对项目代码产生影响)。
  • 如需导入全局第三方工具库或者替换系统方法,请提前考虑和检查该库所产生的影响,评估完成后方可导入。例如:全局返回手势添加、全局键盘管理等。
  • 多Target项目,新添加第三方库,请确认所属Target。

间距和格式

方法声明和定义:应在-或+与返回类型之间使用一个空格,参数类型与*之间建议使用一个空格。如果方法名称较长,且存在多个参数时,建议除一行外,其它参数都应保持单独的一行,且以:对齐。如无法与第一个参数:对齐,则应优先保证其他参数以:对齐。

条件语句:在if,for,while,switch后使用一个空格,并在比较运算符前后使用一个空格。当if存在else时,则应都使用{}

方法调用:确保所有参数在一行或者每个参数一行并以:对齐。当与第一个参数无法对齐时,优先保证后续参数:对齐。

Switch:每个分支建议都必须用大括号括起来,并添加default分支处理。


Objective-C特性

重载生命周期函数:子类控制器中生命周期相关函数,一定要调用父类函数(如不调用须添加注释说明)。例如:[super viewDidLoad];

重载指定构造函数:当在子类中,如果需要init…方法,必须重载父类指定的构造函数。

精简initialize与load的实现代码:避免实现一些复杂且耗时的逻辑。

保持公共API简单:保持公共API简单,避免包含一切功能的API,遵守单一职责。

import 与 #include:使用#import来引用Objective-C/Objective-C++头文件,使用#include引用C/C++头文件。可使用前向声明@class时,优先前向声明。

使用根框架:系统框架应包含根框架,而非单独的文件。

字符串应使用copy关键字:应总是用 copy 属性关键字声明 NSString 属性。

尽量多用类型常量,少用宏定义:尽量不要使用预处理指令定义常量,这样定义出来的常量不含类型信息,编译器只是会在编译前进行查找和替换操作。如果有人重新定义了常量值,这将可能导致程序出现错误。在实现文件中可使用static const定义“只在编译单元内可见的常量”。在头文件中可使用extern或UIKIT_EXTERN来定义全局常量,并在实现文件中定义其值。

代理使用:代理声明应总使用weak修饰,在向代理发送消息的时候,需要判断委托者是否实现了这个代理方法。代理方法声明应合理使用@optional 和@required。

没有实例变量的接口:没有有声明任何实例变量的接口,应省略空大括号。

循环引用:应总是检查并关注VC页面是否正常释放。并在易产生循环引用的地方进行检查。例如block、NSTimer、delegate、子view强引用vc等情况。

单例:单例名称建议采用sharedXXX/SharedInstance/defaultXXX/defaultInstance,必须使用dispatch_once创建。单例中如有block属性,应注意该block是否强引用了某个VC,导致VC不能正常释放。

类结构:生命周期函数应在最上方,其他代码按功能划分即可,不同功能代码块之间应使用pragma mark进行分割。

示例:

#pragma mark – Lifecycle

– (instancetype)init {}

– (void)viewDidLoad {}

– (void)viewWillAppear:(BOOL)animated {}

– (void)didReceiveMemoryWarning {}

– (void)dealloc {}

#pragma mark – Getter

– (NSString *)name;

#pragma mark – Setter

– (void)setName:(NSString *)name;

#pragma mark – Public Methods

– (void)publicMethod {}

#pragma mark – Private Methods

– (void)privateMethod {}

#pragma mark – Some Delegate

#pragma mark – NSCopying

– (id)copyWithZone:(NSZone *)zone {}

#pragma mark – IBActions

– (IBAction)submitData:(id)sender {}


其他内容:

https://github.com/google/styleguide

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html






打赏

尊重原创内容,转载请注明出处
本文链接地址: https://www.awnlab.com/archives/467

为您推荐

发表评论

邮箱地址不会被公开。 必填项已用*标注