iOS代码规范

运算符

  1. 一元运算符与变量之间没有空格
!bValue
~iValue
++iCount
*strSource
&fSum
  1. 二元运算符与变量之间必须有空格
fWidth = 5 + 5;
fLength = fWidth * 2;
fHeight = fWidth + fLength;
for(int i = 0; i < 10; i++)

变量

1.变量名必须使用驼峰格式,自定义类,协议使用大驼峰

SFHomePageViewController

2.对象等局部变量使用小驼峰

NSString *personName = @"";

3.变量的名称必须同时包含功能与类型

UIButton *addButton //添加按钮
UILabel *nameLabel //名字标签
NSArray *nameArray //名字数组
NSDictionary *productDict //产品字典

常量

1.常量以相关类名作为前缀

static const NSTimeInterval YZDLoginAnimateViewFadeOutTime = 0.4;

2.对外公开某个常量,如通知

//.h文件
extern NSString *const YZDLoginOutNotification;
//.m文件
static NSString * const YZDLoginOutNotification = @"YZDLoginOutNotification";

枚举

  1. 使用NS_ENUM进行定义
  2. 对于一些状态 选项的使用枚举
    尽量少用根据数字判断状态少用字符串 数字判断状态
typedef NS_ENUM(NSInteger, DQGameInfoDisplayType) {
    DQGameInfoDisplayTypeDefault = 0,
    DQGameInfoDisplayTypeMatch = 1, //比赛
    DQGameInfoDisplayTypeEvent = 2, //对应节目
};

  1. 宏、常量名都要使用大写字母,用下划线‘_’分割单词
#define URL_GAIN_QUOTE_LIST @"/v1/quote/list"
#define URL_UPDATE_QUOTE_LIST @"/v1/quote/update"
#define URL_LOGIN  @"/v1/user/login”
  1. 宏定义中如果包含表达式或变量,表达式和变量必须用小括号括起来
#define MY_MIN(A, B)  ((A)>(B)?(B):(A))
  1. 开头用k标识,比如Cell的重用字符,k+cell的名称+identifier
#define kGBHomeItemTableViewCellIdentifier = @"kGBHomeItemTableViewCellIdentifier"

属性

  1. 属性的关键字推荐按照原子性,读写,内存管理的顺序排列
@property (nonatomic, readwrite, copy) NSString *name;
@property (nonatomic, readwrite, strong) UIView *headerView;

方法

  1. 方法名中不应使用and,而且签名要与对应的参数名保持高度一致
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
  1. 方法实现时,如果参数过长,则令每个参数占用一行,以冒号对齐
- (void)doSomethingWithFoo:(NSString *)theFoo
                      rect:(CGRect)theRect
                  interval:(CGFloat)theInterval {
   //Implementation
}
  1. 大括号开始与行尾
void function(param1,param2) {
 
}

  1. 类文件名要见名知意
  • Model类名以Model结尾
YZDUserModel
  • 自定义视图命名以View结尾
YZDTabIndexHeaderView
  • 视图控制器命名以ViewController结尾
YZDTabIndexViewController
  1. init && dealloc
// 将 dealloc 方法放在实现文件的最前面
- (void)dealloc {
    // 释放注册的通知和KVO的监听
}
- (instancetype)init { 
    self = [super init]; // call the designated initializer 
    if (self) { 
        // Custom initialization 
    } 
    return self; 
}
  1. 类的头文件中尽量少引用其他头文件
    有时,类A需要将类B的实例变量作为它公共API的属性。这个时候,我们不应该引入类B的头文件,而应该使用向前声明(forward declaring)使用class关键字,并且在A的实现文件引用B的头文件。,这么做的优点:
  • 不在A的头文件中引入B的头文件,就不会一并引入B的全部内容,这样就减少了编译时间。
  • 可以避免循环引用:因为如果两个类在自己的头文件中都引入了对方的头文件,那么就会导致其中一个类无法被正确编译。
// EOCPerson.h
#import
 
@class EOCEmployer;
 
@interface EOCPerson : NSObject
 
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@property (nonatomic, strong) EOCEmployer *employer;//将EOCEmployer作为属性
 
@end
 
// EOCPerson.m
#import "EOCEmployer.h"

但是个别的时候,必须在头文件中引入其他类的头文件:
主要有两种情况:

  • 该类继承于某个类,则应该引入父类的头文件。
  • 该类遵从某个协议,则应该引入该协议的头文件。而且最好将协议单独放在一个头文件中
  1. 头文件.h
  • 方法的参数在一排显示
  • 方法之间保留一行
  • 第一个方法和property保留空行
  • 最后一个方法和@end保留空行
@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, copy) NSString *name;

- (void)testName;

- (void)testAge;

@end
  1. 实现文件.m
  • 引用头文件的顺序
#import <AVFoundation/AVFoundation.h>
#import <Mantle/Mantle.h>
#import "SFUserStatus.h"
  • 类的布局顺序
- (void)dealloc

#pragma mark - Life Cycle Methods
 
#pragma mark - Override Methods
 
#pragma mark - Network Methods
 
#pragma mark - Target Methods
 
#pragma mark - Public Methods
 
#pragma mark - Private Methods
 
#pragma mark - Delegate 
 
#pragma mark - Lazy Loads

分类

  1. 分类添加的方法需要添加前缀和下划线
@interface NSMutableDictionary (DQSafetyCheck)

/**
 *  空值保护 key,value为空时防止crash
 *
 *  @param anObject object
 *  @param aKey     key
 */
- (void)dq_setSafeObject:(id)anObject forKey:(id)aKey;

@end

if语句

  1. 必须列出所有分支(穷举所有的情况),而且每个分支都必须给出明确的结果。推荐这样写
var hintStr;
if (count < 3) {
    hintStr = "Good";
} else {
    hintStr = "";
}

不推荐这样写

var hintStr;
if (count < 3) {
   hintStr = "Good";
}
  1. 不要使用过多的分支,要善于使用return来提前返回错误的情况
    推荐这样写:
- (void)someMethod { 
    if (!goodCondition) {
        return;
    }
    //Do something
}

不推荐这样写:

- (void)someMethod { 
    if (goodCondition) {
        //Do something
    }
}
  1. 条件过多,过长的时候应该换行
if (condition1() && 
    condition2() && 
    condition3() && 
    condition4()) {
  // Do something
}

Switch语句

  1. 每个分支都必须用大括号括起来,每个case都要添加break关键字,避免出现fall-through
switch (integer) {  
    case 1: {
        // ...  
        break; 
     } 
    case 2: {  
        // ...  
      break;  
    }  
    case 3: {
        // ...  
      break; 
    }
    default: {
        // ...  
      break; 
    }
}
  1. 使用枚举类型时,不能有default分支, 除了使用枚举类型以外,都必须有default分支
RWTLeftMenuTopItemType menuType = RWTLeftMenuTopItemMain;  
switch (menuType) {  
    case RWTLeftMenuTopItemMain: {
        // ...  
        break; 
    }
    case RWTLeftMenuTopItemShows: {
        // ...  
        break; 
    }
    case RWTLeftMenuTopItemSchedule: {
        // ...  
        break; 
    }
}

函数

  1. 一个函数的长度不要太长
  2. 一个函数只做一件事(单一原则)
  3. 对于有返回值的函数(方法),每一个分支都必须有返回值
int function() {
    if (condition1) {
        return count1
    } else if (condition2) {
        return count2
    } else {
       return defaultCount
    } 
}
  1. 对输入参数的正确性和有效性进行检查,参数错误立即返回
void function(param1,param2) {
      if (param1 is unavailable) {
           return;
      }
 
      if (param2 is unavailable) {
           return;
      }
 
     //Do some right thing
}

代理、block

  1. 代理,合理的使用optional,required关键字
  2. 向代理、block发送消息时需要判断其是否实现该方法
if ([self.delegate respondsToSelector:@selector(signUpViewControllerDidPressSignUpButton:)]) { 
     [self.delegate signUpViewControllerDidPressSignUpButton:self]; 
}

字符串、数组、字典

取值一定要注意类型、非空、越界等的判断,防止崩溃等问题

  • 字符串
//判断字符串是否是字符串,是否是null,一般从网络获取
static inline BOOL verifiedString(id strlike) {
    if (strlike && ![strlike isEqual:[NSNull null]] && [[strlike class] isSubclassOfClass:[NSString class]] && ((NSString *) strlike).length > 0) {
        return YES;
    } else {
        return NO;
    }
}
// 用法
if (verifiedString(urlString)) {
     // dosomething
}
  • 数组
//判断是否是有效数组,一般从网络获取
static inline BOOL verifiedNSArray(id arraylike) {
    if (arraylike && ![arraylike isEqual:[NSNull null]] && [[arraylike class] isSubclassOfClass:[NSArray class]] && [arraylike count] > 0) {
        return YES;
    } else {
        return NO;
    }
}

// 用法:数组类型 && 未越界
if (verifiedNSArray(self.dataArray) && indexPath.row < self.dataArray.count) {
        
}
  • 字典
// 判断是否是字典,一般从网络获取
static inline BOOL verifiedNSDictionary(id dictlike) {
    if (dictlike && ![dictlike isEqual:[NSNull null]] && [[dictlike class] isSubclassOfClass:[NSDictionary class]]) {
        return YES;
    } else {
        return NO;
    }
}

// 用法:数据的解析
if (verifiedNSDictionary(responseObject)) {

}

注释

优秀的代码大部分是可以自描述的,我们完全可以用程代码本身来表达它到底在干什么,而不需要注释的辅助。

但并不是说一定不能写注释,有以下四种情况比较适合写注释:
公共接口(注释要告诉阅读代码的人,当前类能实现什么功能)。
涉及到比较深层专业知识的代码(注释要体现出实现原理和思想)。
容易产生歧义的代码(但是严格来说,容易让人产生歧义的代码是不允许存在的)。
踩过坑的代码(如特定机型系统会崩溃之类的代码,如有解决方案或链接附上最佳)。

  1. Class注释
/**
 Gif集锦,中间Gif视图
 */
@interface DQGifCollectionGifView : UIView

@end
  1. property注释
@interface DeliveryModel : NSObject

/// 提货劵所在商圈id
@property (nonatomic, assign) long long mallId;
/// 商圈全称
@property (nonatomic, copy) NSString *mallFullName;
/// 商圈简称
@property (nonatomic, copy) NSString *mallShortName;
/// 提货劵号
@property (nonatomic, copy) NSString *credentialsCode;
/// 总金额
@property (nonatomic, assign) NSInteger totalAmount;
  1. 方法注释
/**
 *  圈子列表(达人榜/置顶/贴子列表)
 *
 *  @param urlStr 请求URLStr
 *  @param params 参数
 *  @param block 返回的结果和code
 */
- (void)getCircleRefreshHeadListWithUrl:(NSString *)urlStr params:(NSDictionary *)params resultBackBlock:(DQAnalyzeBackBlock)block;

参考文献

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

推荐阅读更多精彩内容

  • iOS编程规范0规范 0.1前言 为􏰀高产品代码质量,指导广大软件开发人员编写出简洁、可维护、可靠、可 测试、高效...
    iOS行者阅读 4,459评论 21 35
  • 前言 代码规范可以说是老生常谈的话题了, 也是程序员自我修养的一种体现, 虽然一套好的代码规范不能使程序运行的更加...
    kakukeme阅读 1,054评论 0 51
  • 一、命名规范 1、统一要求含义清楚,尽量做到不需要注释也能了解其作用,若做不到,就加注释,使用全称,不使用缩写。 ...
    Untils阅读 564评论 0 0
  • 提起迪丽热巴,她塑造的角色中最讨喜的应该是她在《三生三世十里桃花》中所饰演的凤九。俏皮可爱的她赞美自己姑姑时露出狐...
    神马综艺阅读 2,334评论 0 22
  • 早课:荷花线描 这幅荷花图原本打算昨天一起临的,结果时间不够了。实际今天也是用了一小时。 看起来简单,画起来还是不...
    紫陌来自洗线庐阅读 666评论 2 5