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
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__