Merge pull request #14184 from xiaofeng11/v3_xf

Fix EventListenerCustom registered by UILabel never has been released bug
This commit is contained in:
pandamicro 2015-10-19 17:13:25 +08:00
commit f4a2a53f6d
2 changed files with 84 additions and 3 deletions

View File

@ -204,6 +204,7 @@ EventDispatcher::EventDispatcher()
, _nodePriorityIndex(0)
{
_toAddedListeners.reserve(50);
_toRemovedListeners.reserve(50);
// fixed #4129: Mark the following listener IDs for internal use.
// Therefore, internal listeners would not be cleaned when removeAllEventListeners is invoked.
@ -619,9 +620,13 @@ void EventDispatcher::removeEventListener(EventListener* listener)
if (_inDispatch == 0)
{
listeners->erase(iter);
iter = listeners->erase(iter);
CC_SAFE_RELEASE(l);
}
else
{
_toRemovedListeners.push_back(l);
}
isFound = true;
break;
@ -1152,6 +1157,10 @@ void EventDispatcher::updateListeners(Event* event)
if (!l->isRegistered())
{
iter = sceneGraphPriorityListeners->erase(iter);
// if item in toRemove list, remove it from the list
auto matchIter = std::find(_toRemovedListeners.begin(), _toRemovedListeners.end(), l);
if (matchIter != _toRemovedListeners.end())
_toRemovedListeners.erase(matchIter);
l->release();
}
else
@ -1169,6 +1178,10 @@ void EventDispatcher::updateListeners(Event* event)
if (!l->isRegistered())
{
iter = fixedPriorityListeners->erase(iter);
// if item in toRemove list, remove it from the list
auto matchIter = std::find(_toRemovedListeners.begin(), _toRemovedListeners.end(), l);
if (matchIter != _toRemovedListeners.end())
_toRemovedListeners.erase(matchIter);
l->release();
}
else
@ -1223,6 +1236,11 @@ void EventDispatcher::updateListeners(Event* event)
}
_toAddedListeners.clear();
}
if (!_toRemovedListeners.empty())
{
cleanToRemovedListeners();
}
}
void EventDispatcher::updateDirtyFlagForSceneGraph()
@ -1525,4 +1543,61 @@ void EventDispatcher::setDirty(const EventListener::ListenerID& listenerID, Dirt
}
}
void EventDispatcher::cleanToRemovedListeners()
{
for (auto& l : _toRemovedListeners)
{
auto listenersIter = _listenerMap.find(l->getListenerID());
if (listenersIter == _listenerMap.end())
{
CC_SAFE_RELEASE(l);
continue;
}
bool find = false;
auto listeners = listenersIter->second;
auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
if (sceneGraphPriorityListeners)
{
auto machedIter = std::find(sceneGraphPriorityListeners->begin(), sceneGraphPriorityListeners->end(), l);
if (machedIter != sceneGraphPriorityListeners->end())
{
find = true;
CC_SAFE_RELEASE(l);
sceneGraphPriorityListeners->erase(machedIter);
}
}
if (fixedPriorityListeners)
{
auto machedIter = std::find(fixedPriorityListeners->begin(), fixedPriorityListeners->end(), l);
if (machedIter != fixedPriorityListeners->end())
{
find = true;
CC_SAFE_RELEASE(l);
fixedPriorityListeners->erase(machedIter);
}
}
if (find)
{
if (sceneGraphPriorityListeners && sceneGraphPriorityListeners->empty())
{
listeners->clearSceneGraphListeners();
}
if (fixedPriorityListeners && fixedPriorityListeners->empty())
{
listeners->clearFixedListeners();
}
}
else
CC_SAFE_RELEASE(l);
}
_toRemovedListeners.clear();
}
NS_CC_END

View File

@ -300,7 +300,10 @@ protected:
/** Walks though scene graph to get the draw order for each node, it's called before sorting event listener with scene graph priority */
void visitTarget(Node* node, bool isRootNode);
/** Remove all listeners in _toRemoveListeners list and cleanup */
void cleanToRemovedListeners();
/** Listeners map */
std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap;
@ -318,7 +321,10 @@ protected:
/** The listeners to be added after dispatching event */
std::vector<EventListener*> _toAddedListeners;
/** The listeners to be removed after dispatching event */
std::vector<EventListener*> _toRemovedListeners;
/** The nodes were associated with scene graph based priority listeners */
std::set<Node*> _dirtyNodes;