- 类的头文件中少引入其他头文件,一般情况下,应当在类的头文件中使用向前声明来提及其他类,然后在实现文件中引入其他类的头文件,如果有其他类依赖这个类,并且需要修改这个类的成员变量,则应当在其他类的实现文件中自行引入头文件
- 多使用字面量语法(因为用字面量创建数组或字典时,如果值中有 nil,则会抛出异常,而通过构造方法则不会抛出异常)
- 应该通过取下标操作来访问元素
- 不使用预处理指定定义常量,而是通过 static const 定义常量然后在头文件中用 extern 声明
-
使用 NS ENUM 和 NS
OPTIONS 定义枚举类型,并指明底层数据类型,处理枚举的时候不要实现 default 分支。
- 使用 @property 定义属性
- 在对象内部读取数据时候,直接通过实例变量来读,而写入数据的时候,应该通过属性来写
- 在初始化方法和 dealloc 方法中,总是通过实例变量来读写数据
- 使用懒加载技术配置数据的时候,需要通过属性来读取数据
-
想要检测对象等同性,请提供
isEqual:
和 hash 方法
- 使用类族模式隐藏细节
- 关联对象的使用容易引入难以查找的 bug
- 方法调配可以对现有的实现加入新功能,但是一般情况下只在调试的时候使用,不应当滥用
- 对象类型无法再编译时确定,应当使用类型信息查询方法来探知
- 使用前缀避免命名空间冲突,由于苹果保留了所有两字母前缀,因此应当选用三字母作为前缀
- 类中提供一个全能初始化方法,并在文档中指出,其他初始化方法都调用此方法
- 如果子类中的全能初始化方法与超类不同,则需要覆写超类中的对应方法
- 如果父类中的全能初始化方法不适用于子类,那么应当覆写这个超类方法,并且抛出异常
- 实现 description 方法,如果想要在调试时候打印更详细的对象描述信息,应当实现 debugDescription 方法
- 尽量创建不可变对象,不要公开 mutable collection,而应当提供相关方法。
- 起名的时候应当遵循 OC 规范
- 为私有方法名增加前缀,一般会包含字母 p 和下划线,不要单用一个下划线,这是苹果公司保留的
- ARC 不是异常安全的,因此异常应当不可恢复,其他不严重错误则返回 nil/0 或者使用 NSError
- 类如果需要拷贝功能则应当实现 NSCopying 协议,如果分可变和不可变版本,则应当分别实现 NSCopying 和 NSMutableCopying 协议,一般执行浅拷贝,如果需要深拷贝则应当专门写方法
- 如果有必要可以使用位段结构体来缓存委托对象是否能响应相关协议方法的信息
- 使用分类机制将类的实现代码划分成易于管理的小块,将私有的方法归入 Private 分类,隐藏实现细节
- 向第三方类中添加分类应当为其名称加上前缀,为其方法名加上前缀
- 把全部属性都定义在主接口中,尽量不要在一般分类中定义属性
- 通过 class-continuation 分类新增实例变量,可以在其中将 readonly 改成 readwrite
- 在 ARC 下 dealloc 方法应该释放引用,取消 KVO 和通知,不要做其他事情。如果对象持有文件描述符这样的资源,应当专门编写 close 方法,并且要求使用者调用
- 使用 weak 引用避免保留环
- 自动释放池可以降低内存峰值
- 僵尸对象机制很有用
- 使用 typedef 重新定义 block 类型。
- 使用 block 的时候避免保留环
- 派发队列可以表达同步语义,将同步和异步派发结合起来,实现普通锁机制的同步行为,多使用 GCD,少用 performSelector 系列的方法
- 单例模式使用 dispatch_once 来实现
-
dispatch get
current_queue 已经被弃用
- 多使用 block 来遍历 collection
- NSTimer 会保留目标对象
原文
https://blog.parsedge.com/effective-objective-c/