《编写高质量iOS与OS X代码的52个有效方法》22-27

第22条:理解NSCopying协议

  1. NSZone是以前开发程序时,会据此把内存分成不同的区(zone),而对象会创建在某个区里面。现在不用了,每个程序只有一个区:“默认区”(default zone),所以不用担心其中的zone参数。
  2. 平时我们使用的copy和mutableCopy其实调用的就是copyWithZone和mutableCopyWithZone两个方法
  3. Foundation 框架中的所有 collection 类在默认的情况下都执行浅拷贝
  4. 不要假定遵循了 NSCopying 协议的对象都会执行深拷贝,在绝大多数情况下,执行的都是浅拷贝。如果需要在某对象上执行深拷贝,那么除非该类的文档说它是用深拷贝来实现的 NSCopying 协议的,否则,要么寻找能够执行深拷贝的相关办法,要么自己编写方法来做

要点:

  • 若想令自己所写的对象具有拷贝功能,则需实现NSCoping协议。
  • 如果自定义的对象分为可变版本与不可变版本,那么要同时实现NSCoping与NSMutableCoping协议。
  • 复制对象时需要决定采用浅拷贝还是深拷贝,一般情况下应该尽量执行浅拷贝。
  • 如果你所写的对象需要深拷贝,那么可考虑新增一个专门执行深拷贝的方法。

第23条:通过委托与数据源协议进行对象间通讯

  1. 本类中存放委托对象的这个属性要么定义成weak,要么定义成unsafe_unretained,如果需要在相关对象销毁时自动清空(autoiling),则定义为前者,若不需要自动清空,则定义为后者。

  2. 位段(bitfield)数据类型,这是一项乏人问津的C语言特性,以下didReceiveData三项字段都只占用一个二进制位,可以设置Bool类型来缓存委托对象是否能响应相关协议方法,起优化作用。

     @interface EPCNetworkFetcher() {
     struct {
         unsigned int didReceiveData :1
         unsigned int didFailWithError   :1
         unsigned int didUpdateProgressTo    :1
         }_delegateFlags
     }
    

要点:

  • 委托模式为对象提供了一套接口,使其可由此将相关事件告知其他对象。
  • 将委托对象应该支持的接口定义成协议,在协议中把可能需要处理的事件定为方法。
  • 当某对象需要从另外一个对象中获取数据时,可以使用委托模式。这种情境下,该模式亦称“数据源协议”(data source protocal)。
  • 若有必要,课实现含有位段的结构体,将委托对象是否能响应相关协议方法这一信息缓存至其中。

第24条:将类的实现代码分散到便于管理的数个分类之中

  1. 通过分类机制,可以把类代码分成很多个易于管理的小块,以便单独检视。
  2. 便于调试,对于某个分类中的所有方法来说,分类名称都会出现在其符号中。

要点:

  • 使用分类机制把类的实现代码划分成易于管理的小块。
  • 将应该视为“私有”的方法归入名为Private的分类中,以隐藏实现细节。

第25条:总是为第三方类的分类名称加前缀

  1. 将分类方法加入类中这一操作是在运行期系统加载分类时完成的。
  2. 分类中的方法是直接添加在类里面的,它们就好比这个类中的固有方法。将分类方法加入类中这一操作是在运行期系统加载分类时完成的。运行期系统会把分类中所实现的每个方法都加入类的方法列表中。如果类中本来就有此方法,而分类又实现了一次,那么分类中的方法会覆盖原来那一份实现代码。
  3. 自己实现的分类方法一定要添加前缀,不然覆盖了原有的方法,出现这种bug是很难查找的

要点:

  • 向第三方类中添加分类时,总应给其名称加上你专用的前缀。
  • 向第三方类中添加分类时,总应给其中的方法名加上你专用的前缀。

第26条:勿在分类中声明属性

  1. 可以用关联技术给分类添加属性,但是这样做不太理想。一是要把相似的代码写很多遍,而且在内存管理问题上容易出错,因为我们在为属性实现存取方法时,经常会忘记遵从其内存管理语义。比方说,你可能通过属性特质(attribute)修改了某个属性的内存管理语义。而此时还记得,在设置方法中也得修改设置关联对象时所用的内存管理语义才行。所以说,尽管这个做法不坏,但笔者不推荐。
  2. 属性是用来封装数据的,而分类的目标在于扩展类的功能,而非封装数据

要点:

  • 把封装数据所用的全部属性都定义在主接口里。
  • 在 “class-continuation” 分类之外的其他分类中,可以定义存取方法,但尽量不要定义属性。原因见1

第27条:使用 “class-continuation 分类” 隐藏实现细节

  1. 凡是引入了C++的头文件的类,其实现文件都要更改为可编译OC++文件的.mm格式
  2. 要想使类的代码更易读懂,在编写类的实现代码之前,建议先把方法原型写出来,然后再逐个实现。

要点:

  • 通过 “class-continuation 分类” 想类中新增实例变量。
  • 如果某属性在主接口中声明为 “只读” ,而类的内部又要用设置方法修改此属性,那么就在 “class-continuation 分类” 中将其扩展为 “可读写”。
  • 把私有方法的原型声明在 “class-continuation 分类” 里面。
  • 若想使类所遵循的协议不为人所知,则可于 “class-continuation 分类” 中声明。

你可能感兴趣的:(《编写高质量iOS与OS X代码的52个有效方法》22-27)