iOS Development Guidelines
  • Introduction
  • 规范
    • 0. 介绍
    • 1. 序言
    • 2. 代码命名规范
      • 2.1. 代码命名基础
      • 2.2. 方法(Method)命名
      • 2.3. 函数(Function)命名
      • 2.4. 属性(Property)与数据类型命名
      • 2.5. 其它命名规范
      • 2.6. 可接受缩略名
    • 3. 代码格式规范
      • 3.1. 代码注释格式
      • 3.2. 代码结构与排版
    • 4. 开发实践
      • 4.1. Objective-C保留字
    • 5. Xcode工程结构
    • 6. 版本控制
      • 6.1. Git基本配置
      • 6.2. Git分支模型
      • 6.3. SVN源代码管理规范
      • 6.4. SVN的标准目录结构
    • 7. 附录
      • 7.1. Xcode扩展插件
      • 7.2. 第三方开源库
    • 8. 参考
    • 9. iOS开发优化
  • Swift编码规范
  • Objective-C新特性
  • iOS生命周期
  • Apple 官方设计指南
    • iOS 人机交互指南
      • 概览 - 设计理念
      • 概览 - iOS 10 新功能
      • 概览 - 接口要素
      • 交互 - 3D Touch
      • 交互 - 辅助功能
      • 交互 - 音频
      • 交互 - 身份验证
      • 交互 - 数据输入
      • 交互 - 反馈
      • 交互 - 文件处理
      • 交互 - 初次启动体验
      • 交互 - 手势
      • 交互 - 加载
      • 交互 - 模态
      • 交互 - 导航
      • 交互 - 评分和评论
      • 交互 - 请求权限
      • 交互 - 设置
      • 交互 - 术语
      • 交互 - 撤销与重做
      • 系统功能 - 多任务
      • 系统功能 - 通知
      • 系统功能 - 打印
      • 系统功能 - 快速预览
      • 系统功能 - Siri
      • 系统功能 - TV 供应商
      • 可视化设计 - 动画
      • 可视化设计 - 品牌化
      • 可视化设计 - 颜色
      • 可视化设计 - 布局
      • 图像 - 应用图标
  • Apple 官方开发指南
    • App 发布指南
      • 待完善
    • Cocoa 代码指南
      • 代码命名基础
      • 方法命名
      • 函数命名
      • 属性和数据类型命名
      • 可接受的缩写词和首字母缩写词
      • 针对框架开发者的技术细节
    • 核心蓝牙编程指南
      • 待完善
  • iOS 杂谈
    • Auto Layout 是怎么进行自动布局的性能如何
    • App 启动速度的优化与监控
    • 多人的大项目,架构怎么设计更合理
    • 链接器:符号是怎么绑定到地址上的
    • App 如何通过注入动态库的方式实现极速编译调试
    • 静态分析工具的选择
    • Clang的App 提质
    • 无侵入的埋点方案如何实现
    • 包大小:如何从资源和代码层面实现全方位瘦身
    • iOS 崩溃千奇百怪如何全面监控
    • 如何利用 RunLoop 原理去监控卡顿
    • 临近 OOM,如何获取详细内存分配信息,分析内存问题
    • 日志监控:怎样获取 App 中的全量日志
    • 性能监控:衡量 App 质量的那把尺
    • 远超想象的多线程的那些坑
    • 怎么减少 App 电量消耗
    • 除了 Cocoa,iOS还可以用哪些 GUI 框架开发
    • 细说 iOS 响应式框架变迁,哪些思想可以为我所用
    • 如何构造酷炫的物理效果和过场动画效果
    • A/B 测试:验证决策效果的利器
    • 怎样构建底层的发布和订阅事件总线
    • 如何提高 JSON 解析的性能
    • 如何用 Flexbox 思路开发?跟自动布局比,Flexbox 好在哪
    • 怎么应对各种富文本表现需求
    • 如何在 iOS 中进行面向测试驱动开发和面向行为驱动开发
    • 如何制定一套适合自己团队的 iOS 编码规范
    • iOS 系统内核 XNU:App 如何加载
    • iOS 黑魔法 Runtime Method Swizzling 背后的原理
    • libffi:动态调用和定义 C 函数
    • iOS 是怎么管理内存的
    • 如何编写 Clang 插件
    • 打通前端与原生的桥梁:JavaScriptCore 能干哪些事情
    • React Native、Flutter 等,这些跨端方案怎么选
    • 原生布局转到前端布局,开发思路有哪些转变
    • iOS原生、大前端和Flutter分别是怎么渲染的
    • 剖析使 App 具有动态化和热更新能力的方案
  • Flutter
    • 0.Flutter学习笔记以及问题记录
    • 1.Dart基础快速入门
    • 2.什么是声明式UI
    • 3.Flutter入门基础知识
    • 4.项目结构、资源、依赖和本地化
    • 6.布局与列表
    • 7.状态管理
    • 8.路由与导航
    • 9.手势检测及触摸事件处理
    • 9.线程和异步UI
    • 10.主题和文字处理
    • 11.表单输入与富文本
    • 12.调用硬件、第三方服务以及平台交互、通知
    • 13.基于Http实现网络操作
    • 14.图片控件开发详解
    • 15.异步:Future与FutureBuilder实用技巧
    • 16.APP首页框架搭建-Scaffold与PageView
Powered by GitBook
On this page
  • 代码结构
  • 排版格式
  • 点语法
  • 间距
  • 长度
  • 条件判断
  • 三目运算符
  • 错误处理
  • 方法
  • 变量
  • block
  • 排版格式

Was this helpful?

  1. 规范
  2. 3. 代码格式规范

3.2. 代码结构与排版

代码结构

实现文件中的代码结构,提倡以下约定:

  • 用#pragma mark -将函数或方法按功能进行分组。

  • 建议将dealloc方法放到实现文件的最顶部。

    这样是为了时刻提醒你要记得释放相关资源。

  • delgate或协议相关方法放到一般内容之后。

    #pragma mark - Lifecycle

    - (void)dealloc {}
    - (instancetype)init {}
    - (void)viewDidLoad {}
    - (void)viewWillAppear:(BOOL)animated {}
    - (void)didReceiveMemoryWarning {}

    #pragma mark - Custom Accessors

    - (void)setCustomProperty:(id)value {}
    - (id)customProperty {}

    #pragma mark - Protocol conformance
    #pragma mark - UITextFieldDelegate
    #pragma mark - UITableViewDataSource
    #pragma mark - UITableViewDelegate

    #pragma mark - NSCopying

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

    #pragma mark - NSObject

    - (NSString *)description {}

排版格式

点语法

应该始终使用点语法来访问或者修改属性,访问其他实例时首选括号。

推荐:

view.backgroundColor = [UIColor orangeColor];
[UIApplication sharedApplication].delegate;

反对:

[view setBackgroundColor:[UIColor orangeColor]];
UIApplication.sharedApplication.delegate;

间距

  • 一个缩进使用 4 个空格,永远不要使用制表符(tab)缩进。请确保在 Xcode 中设置了此偏好。

  • 方法的大括号和其他的大括号(if else switch while等)始终和声明在同一行开始,在新的一行结束。

推荐:

if (user.isHappy) {
// Do something
}
else {
// Do something else
}
  • 方法之间应该正好空一行,这有助于视觉清晰度和代码组织性。在方法中的功能块之间应该使用空白分开,但往往可能应该创建一个新的方法。

  • @synthesize和@dynamic在实现中每个都应该占一个新行。

长度

  • 每行代码的长度最多不超过100个字符

  • 尝试将单个函数或方法的实现代码控制在30行内

    如果某个函数或方法的实现代码过长,可以考量下是否可以将代码拆分成几个小的拥有单一功能的方法。

    30行是在13寸macbook上XCode用14号字体时,恰好可以让一个函数的代码做到整屏完全显示的行数。

  • 将单个实现文件里的代码行数控制在500~600行内

    为了简洁和便于阅读,建议将单个实现文件的代码行数控制在500~600行以内最好。

    当接近或超过800行时,就应当开始考虑分割实现文件了。

    最好不要出现代码超过1000行的实现文件。

    我们一般倾向于认为单个文件代码行数越长,代码结构就越不好。而且,翻代码翻的手软啊。

    可以使用Objective-C的Category特性将实现文件归类分割成几个相对轻量级的实现文件。

条件判断

条件判断主体部分应该始终使用大括号{}括住来防止出错,即使它可以不用大括号(例如它只需要一行)。这些错误包括添加第二行(代码)并希望它是 if 语句的一部分时。还有另外一种更危险的,当 if 语句里面的一行被注释掉,下一行就会在不经意间成为了这个 if 语句的一部分。此外,这种风格也更符合所有其他的条件判断,因此也更容易检查。

推荐:

if (!error) {
    return success;
}

反对:

if (!error)
    return success;

或

if (!error) return success;

三目运算符

三目运算符?,只有当它可以增加代码清晰度或整洁时才使用。单一的条件都应该优先考虑使用。多条件时通常使用 if 语句会更易懂,或者重构为实例变量。

推荐:

result = a > b ? x : y;

反对:

result = a > b ? x = c > d ? c : d : y;

错误处理

当引用一个返回错误参数(error parameter)的方法时,应该针对返回值,而非错误变量。

推荐:

NSError *error;
if (![self trySomethingWithError:&error]) {
    // 处理错误
}

反对:

NSError *error;
[self trySomethingWithError:&error];
if (error) {
    // 处理错误
}

一些苹果的 API 在成功的情况下会写一些垃圾值给错误参数(如果非空),所以针对错误变量可能会造成虚假结果(以及接下来的崩溃)。

方法

  • 在方法声明中,在 - + 符号后应该有一个空格。方法片段之间也应该有一个空格。

推荐:

- (void)setExampleText:(NSString *)text image:(UIImage *)image;
  • 实现文件中,方法的左花括号不另起一行,和方法名同行,并且和方法名之间保持1个空格

    此条是为了和Xcode6.1模板生成的文件的代码风格保持一致。

//赞成的
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//不赞成的
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

变量

推荐:

@interface NYTSection: NSObject

@property (nonatomic) NSString *headline;

@end

反对:

@interface NYTSection : NSObject {
    NSString *headline;
}

变量限定符

block

block适合用在 target,selector 模式下创建回调方法时,因为它使代码更易读。块中的代码应该缩进4个空格。 取决于块的长度,下列都是合理的风格准则:

  • 如果一行可以写完块,则没必要换行。

  • 如果不得不换行,关括号应与块声明的第一个字符对齐。

  • 块内的代码须按4空格缩进。

  • 如果块太长,比如超过20行,建议把它定义成一个局部变量,然后再使用该变量。

  • 如果块不带参数,^{之间无须空格。如果带有参数,^(之间无须空格,但) {之间须有一个空格。

// The entire block fits on one line.
[operation setCompletionBlock:^{ [self onOperationDone]; }];

[operation setCompletionBlock:^{
    [self.delegate newDataAvailable];
}];

dispatch_async(fileIOQueue_, ^{
    NSString *path = [self sessionFilePath];
    if (path) {
        ...
    }
});


[[SessionService sharedService]
    loadWindowWithCompletionBlock:^(SessionWindow *window) {
        if (window) {
            [self windowDidLoad:window];
        }
        else {
            [self errorLoadingWindow];
        }
    }
];

[[SessionService sharedService]
    loadWindowWithCompletionBlock:
        ^(SessionWindow *window) {
            if (window) {
                [self windowDidLoad:window];
            }
            else {
                [self errorLoadingWindow];
            }
        }
];


void (^largeBlock)(void) = ^{
    ...
};
[operationQueue_ addOperationWithBlock:largeBlock];

排版格式

- 尽量使用.语法
应该:array.count      
不应该:[array count]

多使用黄金路径
- (void)someMethod {
    if(error) {
        return;
    }
    doSomething
}

而不是:
- (void)someMethod {
    if(!error) {
        doSomething
    }
}

多使用三目运算符:
result = a > b ? x : y;
Previous3.1. 代码注释格式Next4. 开发实践

Last updated 5 years ago

Was this helpful?

变量名应该尽可能命名为描述性的。除了for()循环外,其他情况都应该避免使用单字母的变量名。 星号*表示指针属于变量,例如:NSString *text不要写成NSString* text或者NSString * text,常量除外。 尽量定义属性来代替直接使用实例变量。除了初始化方法(init,initWithCoder:,等),dealloc方法和自定义的 setters 和 getters 内部,应避免直接访问实例变量。更多有关在初始化方法和 dealloc 方法中使用访问器方法的信息,参见。

当在 中引入变量限定符时, 限定符 (__strong,__weak,__unsafe_unretained,__autoreleasing) 应该位于星号和变量名之间,如:NSString * __weak text。

这里
ARC