现在的位置: 首页 > 综合 > 正文

基于cocos2dx引用计数的事件机制

2018年05月27日 ⁄ 综合 ⁄ 共 3264字 ⁄ 字号 评论关闭

设计目的:为了减少类之间的耦合

特性:

0.使用ccobject的引用计数,在调用时不用担心内存释放问题

1.不用继承任何额外的接口或类,只要是cocos2dx内置类的子类都可以使用该机制

使用约束:

0.在注册时会将对象的引用计数加一,反注册时引用计数减一。

1.虽然任意ccobject的子类都可以使用,但是为了自动内存管理,最好在ccnode的子类中使用

1.1 在onEnter时注册事件

1.2 在onExit时反注册

小提示

0.一个事件最好只有一个分发对象,如果出现多个对象分发同一个事件,说明可能代码中有重复的功能。

1.一个函数最好只注册一个事件,以保证函数功能的单一

代码

头文件

//
//  EventController.h
//  LinkBubble3
//
//  Created by user on 13-5-1.
//
//

#ifndef __LinkBubble3__EventController__
#define __LinkBubble3__EventController__
#include "cocos2d.h"
#include <map>
#include <list>

class AppDelegate;

#define EVENT_NAME_SPACE namespace EVENT {
EVENT_NAME_SPACE

enum type{
    LIFECHANGE= 0,
};

//事件回调
typedef void (cocos2d::CCObject::*SEL_EVENT_CALL)(int,int);
#define eventfunc_selector(_SELECTOR) (EVENT::SEL_EVENT_CALL)(&_SELECTOR)


class EventController :public cocos2d::CCObject {
    class EventWraper
    {
    private:
        cocos2d::CCObject* obj;
        SEL_EVENT_CALL callBack;
    public:
        EventWraper(cocos2d::CCObject* o =NULL,SEL_EVENT_CALL c=NULL)
        :obj(o),callBack(c)
        {
            CC_SAFE_RETAIN(obj);
        }
        ~EventWraper(){CC_SAFE_RELEASE_NULL(obj);}
        EventWraper(const EventWraper& r)
        {
            obj=r.obj;
            callBack= r.callBack;
            CC_SAFE_RETAIN(obj);
        }
        const EventWraper& operator =(const EventWraper& r)
        {
            if(this == &r){return *this;}
            CC_SAFE_RELEASE_NULL(obj);
            obj=r.obj;
            callBack= r.callBack;
            CC_SAFE_RETAIN(obj);
            return *this;
        }
        bool operator ==(const EventWraper& r)const
        {
            return obj == r.obj && callBack == r.callBack;
        }
        void Call(int param1,int param2)
        {
            if(obj != NULL)
            {
                (obj->*callBack)(param1,param2);
            }
        }
        
    };
    
    typedef std::list<EventWraper> EventList;
    typedef std::map<type, EventList> TypeToEventListMap;
    
    TypeToEventListMap m_mapEventObjs;

    EventController(const EventController&) = delete;
    const EventController& operator =(const EventController&)=delete;
    EventController(){}
    friend class AppDelegate;
public:
    void Register(type t,cocos2d::CCObject* pObj,SEL_EVENT_CALL callBack);
    void UnRegister(type t,cocos2d::CCObject* pObj,SEL_EVENT_CALL callBack);
    void Dispatch(type t,int param1=0,int param2=0);
        
};

EventController* GetController();

#define REG_EVENT(type,Class,Func) EVENT::GetController()->Register(type, this, eventfunc_selector(Class::Func))
#define UNREG_EVENT(type,Class,Func) EVENT::GetController()->UnRegister(type, this, eventfunc_selector(Class::Func))
}

#endif /* defined(__LinkBubble3__EventController__) */

cpp

//
//  EventController.cpp
//  LinkBubble3
//
//  Created by user on 13-5-1.
//
//

#include "EventController.h"
#include "AppDelegate.h"

EVENT_NAME_SPACE

EventController* GetController()
{return &AppDelegate::Instance()->eventController;}


void EventController::Register(EVENT::type t, cocos2d::CCObject *pObj, SEL_EVENT_CALL callBack)
{
    auto iterEvent = m_mapEventObjs.find(t);
    if (iterEvent == m_mapEventObjs.end()) {
        iterEvent = m_mapEventObjs.insert(std::make_pair(t, EventList())).first;
    }
    EventWraper wraper(pObj,callBack);
    EventList& list = iterEvent->second;
    if (std::find(list.begin(), list.end(), wraper) == list.end()) {
        list.push_back(wraper);
    }
}

void EventController::UnRegister(EVENT::type t, cocos2d::CCObject *pObj, SEL_EVENT_CALL callBack)
{
    auto iterEvent = m_mapEventObjs.find(t);
    if (iterEvent == m_mapEventObjs.end()) {
        return;
    }
    EventWraper wraper(pObj,callBack);
    EventList& list = iterEvent->second;
    list.remove(wraper);
}

void EventController::Dispatch(type t,int param1,int param2)
{
    for (auto iterEvent = m_mapEventObjs.begin(); iterEvent != m_mapEventObjs.end(); ++iterEvent) {
        EventList& objList = iterEvent->second;
        for (auto itCall = objList.begin(); itCall != objList.end(); ++itCall) {
            itCall->Call(param1, param2);
        }
    }
}


}

抱歉!评论已关闭.