协议与分类

Tuesday, January 30, 2018

通过委托与数据源协议进行对象间通信

  • 如果要在委托对象上调用可选方法,那么必须提前使用类型类型信息查询方法判断这个委托对象能否响应相关的选择子。即 respondsToSelector

  • 在调用 delegate 对象中的方法时,总是应该把发起委托的实例也一并传入方法中,这样,delegate 对象在实现相关方法时,就能根据传入的实例分别执行不同的代码了。

  • 如果某对象需要从另外一个对象获取数据,也可以用委托模式,该模式也称为数据源模式(dataSource)

    - (void)networkFetcher:(EOCNetworkFetcher *)fetcher { if (fetcher == _myFetcherA) {

            }else if (fetcher == _myFetcherB) {
    
            }
    

    }

  • 通常把委托对象能否响应某个协议方法这一信息缓存起来,以优化程序效率,否则就会一直使用 respondsToSelector 方法,所以我们可以把是否实现了相关的方法这一信息缓存起来,创建的结构体只有大小为1的位段,那么就能把许多 boolean 值塞入一小块数据里。

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

    //重写 setDelegate 方法

    • (void)setDelegate:(id)delegate { _delegate = delegate; _delegateFlags.didReceiveData = [delegate respondsToSelector: @selector(networkFetcher: didReceiveData:)]; }

    //这样,每次查询就可以直接查询标记,而不用去使用 respondsToSelector }

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

  • 如果一个类的方法很多,那么源代码文件会越来越大,并且难以管理,应该把类分成不同的几个部分。可以使用『分类』机制把类改写。
  • 分类之后,可以保留在一个文件中,也能把各个分类提取到各自的文件中。
  • 即使类本身功能不大,我们也可以用分类机制把类切割成几块,把相应的代码归入到不同的功能区。
  • 可以将私有方法放到归入到 private 的分类中,以隐藏实现细节。

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

  • 使用分类也容易出现可能产生的问题,运行期系统会把分类中实现的方法加入到类的方法列表中。如果类本来就有该方法,分类也有,那分类的方法会覆盖掉。而且如果多个分类都有实现方法,多次覆盖以最后一次为准。
  • 为解决上述问题,一般是将方法名加上前缀

不要在分类中声明属性

  • 除了 class-continuation 分类,其它分类都无法向类增加实例变量,它们无法把实现属性所需的实例变量合成出来。
  • 如果要在分类中合成实例变量,可以用动态转发和关联对象的方法解决。

使用 class-continuation 分类隐藏实现细节

  • 一种合理的用法是在 public 接口声明为只读的属性扩展为可读写,以便在内部设置其值。
  • 为了增加可读性,可以把私有方法原型声明在 class-continuation 里
  • 如果不想让人知道类遵循的协议,也可以放到 class-continuation 里

通过协议提供匿名对象

  • 协议可以提供匿名类型。具体的对象类型可以淡化成遵从某协议的 id 类型,协议里规定了对象所应实现的方法。
  • 使用匿名对象来隐藏类型名称或类名
Objective-C

内存管理

接口与 API 设计