Code Monkey home page Code Monkey logo

dznotificationcenter's Introduction

DZNotificationCenter

一个优化版的由中心枢纽的通知中心

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

  1. 每个注册的地方需要同时注册一个函数,这将会带来大量的编码工作。仔细分析能够发现,其实我们每个观察者每次注册的函数几乎都是雷同的。这就是种变相的CtrlCV,是典型的丑陋和难维护的代码。

  2. 每个观察者的回调函数,都需要对主题对象发送来的消息进行解包的操作。从UserInfo中通过KeyValue的方式,将消息解析出来,而后进行操作。试想一下,工程中有100个地方,同时对前面中在响应变化的函数中进行了解包的操作。而后期需求变化需要多传一个内容的时候,将会是一场维护上的灾难。

  3. 当大规模使用观察者模式的时候,我们往往在dealloc处加上一句:
    [[NSNotificationCenter defaultCenter] removeObserver:self]
    而在实际使用过程中,会发现该函数的性能是比较低下的。在整个启动过程中,进行了10000次RemoveObserver操作,

    @implementation DZMessage
    - (void) dealloc
    {
       [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    ....
    
	
	```
   for (int i = 0 ; i < 10000; i++) {
        DZMessage* message = [DZMessage new];
    }
通过下图可以看出这一过程消耗了23.4%的CPU,说明这一函数的效率还是很低的。	![image](http://image226-c.poco.cn/mypoco/myphoto/20140111/21/17448668720140111213040027.jpg)

这还是只有一种消息类型的存在下有这样的结果,如果整个NotificationCenter中混杂着多种消息类型,那么恐怕对于性能来说将会是灾难性的。

```

for (int i = 0 ; i < 10000; i++) { DZMessage* message = [DZMessage new]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handle) name:[@(i) stringValue] object:nil]; }

	增加了多种消息类型之后,RemoveObserver占用了启动过程中63.9%的CPU消耗。
![image](http://image226-c.poco.cn/mypoco/myphoto/20140111/21/17448668720140111215636037.jpg)
	而由于Apple没有提供Center的源码,所以修改这个Center几乎不可能了。

######改进版的有中心观察者模式(DZNotificationCenter)
[GitHub地址](https://github.com/yishuiliunian/DZNotificationCenter.git)
在设计的时候考虑到以上用起来不爽的地方,进行了优化:

1. 将解包到执行函数的操作进行了封装,只需要提供某消息类型的解包block和消息类型对应的protocol,当有消息到达的时候,消息中心会进行统一解包,并直接调用观察者相应的函数。
2. 对观察者的维护机制进行优化(还未做完),提升查找和删除观察者的效率。

DZNotificationCenter的用法和NSNotificationCenter在注册和注销观察者的地方是一样的,不一样的地方在于,你在使用的时候需要提供解析消息的block。你可以通过两种方式来提供。

* 直接注册的方式

	```
[DZDefaultNotificationCenter addDecodeNotificationBlock:^SEL(NSDictionary *userInfo, NSMutableArray *__autoreleasing *params) {
        NSString* key = userInfo[@"key"];
        if (params != NULL) {
            *params = [NSMutableArray new];
        }
        [*params  addObject:key];
        return @selector(handleTestMessageWithKey:);
    } forMessage:kDZMessageTest];
  • 实现DZNotificationInitDelegaete协议,当整个工程中大规模使用观察者的时候,建议使用该方式。这样有利于统一管理所有的解析方式。
- (DZDecodeNotificationBlock) decodeNotification:(NSString *)message forCenter:(DZNotificationCenter *)center
{
    if (message == kDZMessageTest) {
        return ^(NSDictionary* userInfo, NSMutableArray* __autoreleasing* params){
            NSString* key = userInfo[@"key"];
            if (params != NULL) {
                *params = [NSMutableArray new];
            }
            [*params  addObject:key];
            return @selector(handlePortMessage:);
        };
    }
    return nil;
}

在使用的过程中为了,能够保证在观察者处能够回调相同的函数,可以实现针对某一消息类型的protocol

@protocol DZTestMessageInterface <NSObject>
- (void) handleTestMessageWithKey:(NSString*)key;
@end

这样就能够保证,在使用观察者的地方不用反复的拼函数名和解析消息内容了。

@interface DZViewController () <DZTestMessageInterface>
@end
@implementation DZViewController
....
- (void) handleTestMessageWithKey:(NSString *)key
{
    self.showLabel.text = [NSString stringWithFormat:@"get message with %@", key];
}
....

dznotificationcenter's People

Contributors

tencentwallet avatar yishuiliunian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

dznotificationcenter's Issues

性能问题可以忽略

我觉得你所提出的性能问题是不靠谱的,在实际的应用场景中,根本不可能同时间连续发出成千上万次的通知,也不可能存在成千上万个对象监听同一个消息。假如真的是这样,这说明开发人员的设计有问题。另外我认为CPU占用高不等同于效率低下,你可以试连续执行你认为效率高的方法10000次,看看效果如何?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.