CCNotificationCenter(中心类addObserver postNotification m_observers. CCNoti..Observer类 performSelector)

实现步骤:

1、添加观察者:

在任何地方,只要你你对某个消息感兴趣(和pureMVC中的listNotification一样),你就可以在那里监听该消息。

void addObserver(CCObject* target,SEL_CallFuncO callBack,const char* name, CCObject* data);

参数1为事件监听的目标,参数2为回调函数(即接收到消息后执行的函数),参数3为消息名,参数4为消息体。

参数1 -这个观察者所处object(即工作区)Adds an observer for the specified target

具体实现如下:

    CCNotificationCenter::sharedNotificationCenter()->addObserver(this,
callfunco_selector(GameLayer::callBack),
name,
NULL
复制代码

1、发送消息:
在需要发送消息的地方,调用postNotification方法即可,postNotification有两种,可以不带数据和带数据。
void postNotification(const char* name);
void postNotification(const char* name,CCObject* data);

name是消息名,是消息唯一标识,在整个游戏过程中是唯一的,因此,我们一般把所有的消息名放在一个头文件中,纺织消息名重复,data是消息体,即发送的数据。

发送通知如下:

CCNotificationCenter::sharedNotificationCenter()->postNotification(name);

3、释放消息观察者:

释放消息观察者是很重要的,不释放的话,会产生内存泄露。我们需要在onExit()方法里面,释放消息观察者。


void GameLayer::onExit(){
     CCLayer::onExit();
     CCNotificationCenter::sharedNotificationCenter()->removeObserver(
this,
name //消息名 ); }




#ifndef __CCNOTIFICATIONCENTER_H__

#define __CCNOTIFICATIONCENTER_H__


#include "cocoa/CCObject.h"

#include "cocoa/CCArray.h"


NS_CC_BEGIN


class CC_DLL CCNotificationCenter : public CCObject

{

public:

    /** CCNotificationCenter constructor */

    CCNotificationCenter();


    /** CCNotificationCenter destructor */

    ~CCNotificationCenter();

    

    /** Gets the single instance of CCNotificationCenter. */

    static CCNotificationCenter *sharedNotificationCenter(void);


    /** Destroys the single instance of CCNotificationCenter. */

    static void purgeNotificationCenter(void);


    /** @brief Adds an observer for the specified target.

     *  @param target The target which wants to observe notification events.

     *  @param selector The callback function which will be invoked when the specified notification event was posted.

     *  @param name The name of this notification.

     *  @param obj The extra parameter which will be passed to the callback function.

     */

    voidaddObserver(CCObject *target, 

                     SEL_CallFuncO selector,

                     const char *name,

                     CCObject *obj);

{

    if (this->observerExisted(target, name))  //在这里判断观察者数组里是否已经有了 同一个工作区(target)的 并且同消息名的 观察者 避免重复add(不同工作区却监听同名消息的 观察者都会被add到observers里  并在post 对应消息名时 独立的执行各自的不同回调)

        return;

    

    CCNotificationObserver *observer = new CCNotificationObserver(target, selector, name, obj);

    if (!observer)

        return;

    

    observer->autorelease();

    m_observers->addObject(observer);

}


    /** @brief Removes the observer by the specified target and name.

     *  @param target The target of this notification.

     *  @param name The name of this notification. 

     */

    void removeObserver(CCObject *target,const char *name);

    

    /** @brief Removes all notifications registered by this target

     *  @param target The target of this notification.

     *  @returns the number of observers removed

     */

    int removeAllObservers(CCObject *target);


    /** @brief Registers one hander for script binding.

     *  @note Only supports Lua Binding now.

     *  @param handler The lua handler.

     */

    void registerScriptObserver(CCObject *target,int handler,const char* name);


    /** Unregisters script observer */

    void unregisterScriptObserver(CCObject *target,const char* name);

    

    /** @brief Posts one notification event by name.

     *  @param name The name of this notification.

     */

    void postNotification(const char *name);


    /** @brief Posts one notification event by name.

     *  @param name The name of this notification.

     *  @param object The extra parameter.

     */

    voidpostNotification(const char *name, CCObject *object);//post的同时 会去消息中心里的 观察者数组寻找是否有 post的 观察者 如果有(只会比对消息名 和消息体) 则调用观察者的回调

{

    CCArray* ObserversCopy = CCArray::createWithCapacity(m_observers->count());

    ObserversCopy->addObjectsFromArray(m_observers);

    CCObject* obj = NULL;

    CCARRAY_FOREACH(ObserversCopy, obj)

    {

        CCNotificationObserver* observer = (CCNotificationObserver*) obj;

        if (!observer)

            continue;

        

        if (!strcmp(name,observer->getName()) && (observer->getObject() == object || observer->getObject() == NULL || object == NULL))

//注意上面的判断  当addobserve时传的消息体是null或者 post的消息体是 null 或者两者都不是Null并且相同 则执行观察者回调 回调参数是post时的 消息体 --所以addobserve时的消息体无关紧要

        {

            if (0 != observer->getHandler()) //如果观察者m_nHandler不为空  执行脚本回调  否则执行 回调

            {

                CCScriptEngineProtocol* engine = CCScriptEngineManager::sharedManager()->getScriptEngine();

                engine->executeNotificationEvent(this, name);

            }

            else

            {

                observer->performSelector(object);

            }

        }

    }

}


    

    /** @brief Gets script handler.

     *  @note Only supports Lua Binding now.

     *  @return The script handle.

     */

    inline int getScriptHandler() { return m_scriptHandler; };

    

    /** @brief Gets observer script handler.

     *  @param name The name of this notification.

     *  @return The observer script handle.

     */

    int getObserverHandlerByName(const char* name);

private:

    // internal functions


    // Check whether the observer exists by the specified target and name.

    bool observerExisted(CCObject *target,const char *name);

    

    // variables

    //

    CCArray *m_observers;

    int     m_scriptHandler;

};


class CC_DLLCCNotificationObserver : public CCObject //观察者类   一个观察者创建需要4个参数 1、工作区2、回调方法 3、观察的消息名 4、消息体 作为回调时的参数  观察者封装了调用其本身回调的方法  ----  参数1 参数3 在addobserve时分辨是否是已经加入的观察者 时使用     参数234 在post时调用回调时使用当addobserve时传的消息体是null或者 post的消息体是 null 或者两者都不是Null并且相同 则执行观察者回调 回调参数是post时的 消息体 --所以addobserve时的消息体无关紧

{

public:

    /** @brief CCNotificationObserver constructor

     *  @param target The target which wants to observer notification events.  //观察者所在的类或层。。 即观察者工作区

     *  @param selector The callback function which will be invoked when the specified notification event was posted. //观察的消息post后的回调

     *  @param name The name of this notification.//消息名

     *  @param obj The extra parameter which will be passed to the callback function.//消息体

     */

   CCNotificationObserver(CCObject *target, 

                           SEL_CallFuncO selector,

                           const char *name,

                           CCObject *obj);

{

    m_target = target;

    m_selector = selector;

    m_object = obj;

    

    m_name = new char[strlen(name)+1];

    memset(m_name,0,strlen(name)+1);

    

    string orig (name);

    orig.copy(m_name,strlen(name),0);

    m_nHandler = 0;

}


    /** CCNotificationObserver destructor function */

    ~CCNotificationObserver();      

    

    /** Invokes the callback function of this observer */

    voidperformSelector(CCObject *obj);  //执行回调 如果参数为0 则默认回调参数是消息体

{

    if (m_target)

    {

if (obj) {

(m_target->*m_selector)(obj);

} else {

(m_target->*m_selector)(m_object);

}

    }

}


private:

    CC_PROPERTY_READONLY(CCObject *, m_target, Target);//观察者工作区

    CC_PROPERTY_READONLY(SEL_CallFuncO, m_selector, Selector); //回调

    CC_PROPERTY_READONLY(char *, m_name, Name);     //消息名

    CC_PROPERTY_READONLY(CCObject *, m_object, Object);  //消息体 同时也是回调的参数

    CC_PROPERTY(int, m_nHandler,Handler);

};


NS_CC_END


#endif//__CCNOTIFICATIONCENTER_H__


你可能感兴趣的:(CCNotificationCenter(中心类addObserver postNotification m_observers. CCNoti..Observer类 performSelector))