最近的项目需要修改到按键相关的处理,于是顺便把这部分相关的代码看了一遍。
头文件
// 支持的2种按键消息 typedef enum { // the back key clicked msg kTypeBackClicked = 1,kTypeMenuClicked,} ccKeypadMSGType; struct _ccCArray; // 按键分发类 class CC_DLL CCKeypadDispatcher : public CCObject { public: CCKeypadDispatcher(); ~CCKeypadDispatcher(); // 添加delegate forceAddDelegate void addDelegate(CCKeypadDelegate* pDelegate); // 移除delegate 最后都是执行forceRemoveDelegate void removeDelegate(CCKeypadDelegate* pDelegate); // 添加delegate void forceAddDelegate(CCKeypadDelegate* pDelegate); // 移除delegate void forceRemoveDelegate(CCKeypadDelegate* pDelegate); // 按键分发 bool dispatchKeypadMSG(ccKeypadMSGType nMsgType); protected: // delegate数组 CCArray* m_pDelegates; bool m_bLocked; // 用于锁定 bool m_bToAdd; // 需要执行添加的标记 bool m_bToRemove; // 需要执行删除的标记 struct _ccCArray *m_pHandlersToAdd; // 需要添加的handler struct _ccCArray *m_pHandlersToRemove; // 需要移除的handler };
实现
CCKeypadDispatcher::CCKeypadDispatcher() : m_bLocked(false),m_bToAdd(false),m_bToRemove(false) { m_pDelegates = CCArray::create(); m_pDelegates->retain(); m_pHandlersToAdd = ccCArrayNew(8); m_pHandlersToRemove = ccCArrayNew(8); } CCKeypadDispatcher::~CCKeypadDispatcher() { CC_SAFE_RELEASE(m_pDelegates); if (m_pHandlersToAdd) { ccCArrayFree(m_pHandlersToAdd); } if (m_pHandlersToRemove) { ccCArrayFree(m_pHandlersToRemove); } } void CCKeypadDispatcher::removeDelegate(CCKeypadDelegate* pDelegate) { if (!pDelegate) { return; } // 如果当前没有锁定,直接移除 if (! m_bLocked) { forceRemoveDelegate(pDelegate); } // 如果当前锁定,则先将要移除的加入到待移除数组,并设置标记,在锁定结束后会再移除 else { ccCArrayAppendValue(m_pHandlersToRemove,pDelegate); m_bToRemove = true; } } // 思路同移除 void CCKeypadDispatcher::addDelegate(CCKeypadDelegate* pDelegate) { if (!pDelegate) { return; } if (! m_bLocked) { forceAddDelegate(pDelegate); } else { ccCArrayAppendValue(m_pHandlersToAdd,pDelegate); m_bToAdd = true; } } void CCKeypadDispatcher::forceAddDelegate(CCKeypadDelegate* pDelegate) { // 添加 CCKeypadHandler* pHandler = CCKeypadHandler::handlerWithDelegate(pDelegate); if (pHandler) { m_pDelegates->addObject(pHandler); } } void CCKeypadDispatcher::forceRemoveDelegate(CCKeypadDelegate* pDelegate) { // 从当前数组中查找到对应的delegate,然@R_502_424@删除,只删除从前往后第一个找到的值 CCKeypadHandler* pHandler = NULL; CCObject* pObj = NULL; CCARRAY_FOREACH(m_pDelegates,pObj) { pHandler = (CCKeypadHandler*)pObj; if (pHandler && pHandler->getDelegate() == pDelegate) { m_pDelegates->removeObject(pHandler); break; } } } bool CCKeypadDispatcher::dispatchKeypadMSG(ccKeypadMSGType nMsgType) { CCKeypadHandler* pHandler = NULL; CCKeypadDelegate* pDelegate = NULL; // 锁定 防止分发的时候被莫名其妙移除了 m_bLocked = true; if (m_pDelegates->count() > 0) { CCObject* pObj = NULL; // 按照添加顺序依次分发 CCARRAY_FOREACH(m_pDelegates,pObj) { CC_BREAK_IF(!pObj); pHandler = (CCKeypadHandler*)pObj; pDelegate = pHandler->getDelegate(); // 目前只有2种事件 switch (nMsgType) { case kTypeBackClicked: pDelegate->keyBackClicked(); break; case kTypeMenuClicked: pDelegate->keyMenuClicked(); break; default: break; } } } // 锁定解除 m_bLocked = false; // 如果锁定期间有添加或者移除的,现在执行掉,执行完毕后清空待处理的数组 if (m_bToRemove) { m_bToRemove = false; for (unsigned int i = 0; i < m_pHandlersToRemove->num; ++i) { forceRemoveDelegate((CCKeypadDelegate*)m_pHandlersToRemove->arr[i]); } ccCArrayRemoveAllValues(m_pHandlersToRemove); } if (m_bToAdd) { m_bToAdd = false; for (unsigned int i = 0; i < m_pHandlersToAdd->num; ++i) { forceAddDelegate((CCKeypadDelegate*)m_pHandlersToAdd->arr[i]); } ccCArrayRemoveAllValues(m_pHandlersToAdd); } return true; }