知乎上看到一个问题《一百行以下有那些给力代码》,几乎所有回答都是用 100 行实现的某个小功能,有趣归有趣,但对实际工作并没有什么帮助。翻了翻自己的 M80Kit ,里面也有些比较有趣且实用的辅助类都是一百行左右,可以拿出来秀下。
M80MulticastDelegate
一个从 XMPP 框架中抽离出来的类,提供同步的一对多 delegate 机制。
在很多场景下,往往多个对象会依赖于某个核心对象。使用 M80MulticastDelegate 就能够很好地进行解耦:不需要定义过多正式的protocol 或者 notification 进行通信。巧妙地利用 OC 的消息转发机制,当发一个不认识的消息给当前 MulticaseDelegate 时,它就会自动进行转发:遍历已注册的 delegate node,找到能够响应当前 selector 的 node 并执行。
M80TimerHolder
一个 NSTimer 的 Wrapper,用于 NSTimer 的管理。iOS 上 NSTimer 的最大坑是它会 retain 当前 target,这样就导致了 target 的延迟释放甚至无法释放(repeat 为 YES 的 NSTimer 和 target 形成 retain-cycle 又没有合理时机进行 invalidate)。
一种通用的解决方式是用 Block 来解除 retain-cycle,但需要在 block 中将 target 设为 weak,这是这种方式比较容易出错的地方。
而 M80TimerHolder 则采用稍微有点耦合但更安全的方式:真正的 Target (通常是VC)和 NSTimer 持有 M80TimerHolder,后者通过weak delegate和 VC 进行通信。对于 repeat 的 Timer,没有即使不做任何处理都不会有延迟处理和 retain-cycle 的问题。而对于repeat 的 Timer 只需要在 VC 的 dealloc 方法调用 M80TimerHolder 的 stopTimer 方法即可。就算不调用,形成 retain-cycle 的也仅仅是 Timer 和 M80TimerHolder,并不会对 APP 后续执行造成任何影响,只是多了个空跑的 Timer 和泄露的M80TimerHolder 而已。
具体实现如下:
M80WeakProxy
顾名思义,这是个代理,解决的问题和 M80TimeHolder 一样:使得 NSTimer 不持有 target 以免形成 retain-cycle。原理很简单:NSTimer 持有 M80WeakProxy,而 M80WeakProxy 只持有真正 target 的虚引用,并通过 OC 的消息转发机制调用 target 的onTimer 方法。(Fork from FLAnimatedImage)
具体实现如下
而真正调用时候只需要这样:
M80Observer
用Block实现KVO,规避KVO register和unregister没有配对调用的问题。同样不超过150行,采用的原理和C++中实现自动锁之类的方式相近,在类初始化时register KVO,析构时unregister KVO以形成配对的调用。