IOS观察者设计模式

2020-01-14 17:24:44于海丽

一次完整的观察过程如上图所示。整个过程中,关键的类有这么几个(介绍顺序按照完成顺序):

观察者Observer,一般继承自NSObject,通过NSNotificationCenter的addObserver:selector:name:object接口来注册对某一类型通知感兴趣.在注册时候一定要注意,NSNotificationCenter不会对观察者进行引用计数+1的操作,我们在程序中释放观察者的时候,一定要去报从center中将其注销了。


- (void) handleMessage:(NSNotification*)nc{
//解析消息内容
NSDictionary* userInfo = [nc userInfo];
}
- (void) commonInit
{
//注册观察者
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMessage:) name:kDZTestNotificatonMessage object:nil];
}

通知中心NSNotificationCenter,通知的枢纽。
主题对象,被观察的对象,通过postNotificationName:object:userInfo:发送某一类型通知,广播改变。


- (void) postMessage
{
[[NSNotificationCenter defaultCenter] postNotificationName:kDZTestNotificatonMessage object:Nil userInfo:@{}];
}

通知对象NSNotification,当有通知来的时候,Center会调用观察者注册的接口来广播通知,同时传递存储着更改内容的NSNotification对象。

apple版实现的NotificationCenter让我用起来不太爽的几个小问题

在使用NSNotificationCenter的时候,从编程的角度来讲我们往往不止是希望能够做到功能实现,还能希望编码效率和整个工程的可维护性良好。而Apple提供的以NSNotificationCenter为中心的观察者模式实现,在可维护性和效率上存在以下缺点:

每个注册的地方需要同时注册一个函数,这将会带来大量的编码工作。仔细分析能够发现,其实我们每个观察者每次注册的函数几乎都是雷同的。这就是种变相的CtrlCV,是典型的丑陋和难维护的代码。
每个观察者的回调函数,都需要对主题对象发送来的消息进行解包的操作。从UserInfo中通过KeyValue的方式,将消息解析出来,而后进行操作。试想一下,工程中有100个地方,同时对前面中在响应变化的函数中进行了解包的操作。而后期需求变化需要多传一个内容的时候,将会是一场维护上的灾难。

当大规模使用观察者模式的时候,我们往往在dealloc处加上一句:

[[NSNotificationCenter defaultCenter] removeObserver:self]

而在实际使用过程中,会发现该函数的性能是比较低下的。在整个启动过程中,进行了10000次RemoveObserver操作,