diff --git a/cocos/base/CCVector.h b/cocos/base/CCVector.h index 67485d1641..dbf3f80435 100644 --- a/cocos/base/CCVector.h +++ b/cocos/base/CCVector.h @@ -309,18 +309,38 @@ public: last->release(); } - /** @brief Remove a certain object. + /** @brief Remove a certain object in Vector. * @param object The object to be removed. - * @param toRelease Whether to decrease the referece count of the deleted object. + * @param removeAll Whether to remove all elements with the same value. */ - void eraseObject(T object, bool toRelease = true) + void eraseObject(T object, bool removeAll = false) { CCASSERT(object != nullptr, "The object should not be nullptr"); - auto iter = std::find(_data.begin(), _data.end(), object); - if (iter != _data.end()) - _data.erase(iter); - if (toRelease) - object->release(); + + if (removeAll) + { + for (auto iter = _data.begin(); iter != _data.end();) + { + if ((*iter) == object) + { + iter = _data.erase(iter); + object->release(); + } + else + { + ++iter; + } + } + } + else + { + auto iter = std::find(_data.begin(), _data.end(), object); + if (iter != _data.end()) + { + _data.erase(iter); + object->release(); + } + } } /** @brief Removes from the vector with an iterator. diff --git a/extensions/GUI/CCControlExtension/CCControl.cpp b/extensions/GUI/CCControlExtension/CCControl.cpp index 278f822e9b..04cd0219d0 100644 --- a/extensions/GUI/CCControlExtension/CCControl.cpp +++ b/extensions/GUI/CCControlExtension/CCControl.cpp @@ -186,7 +186,7 @@ void Control::removeTargetWithActionForControlEvent(Ref* target, Handler action, //remove all invocations if the target and action are null //TODO: should the invocations be deleted, or just removed from the array? Won't that cause issues if you add a single invocation for multiple events? - bool bDeleteObjects=true; + if (!target && !action) { //remove objects @@ -215,7 +215,7 @@ void Control::removeTargetWithActionForControlEvent(Ref* target, Handler action, } for(const auto &invocation : tobeRemovedInvocations) { - eventInvocationList.eraseObject(invocation, bDeleteObjects); + eventInvocationList.eraseObject(invocation); } } } diff --git a/tests/test-cpp/Classes/UnitTest/UnitTest.cpp b/tests/test-cpp/Classes/UnitTest/UnitTest.cpp index 86933366b0..04366e651d 100644 --- a/tests/test-cpp/Classes/UnitTest/UnitTest.cpp +++ b/tests/test-cpp/Classes/UnitTest/UnitTest.cpp @@ -233,6 +233,47 @@ void TemplateVectorTest::onEnter() vec6.eraseObject(vec6.at(2)); CCASSERT(vec6.at(2)->getTag() == 1013, ""); vec6.clear(); + + auto objA = Node::create(); // retain count is 1 + auto objB = Node::create(); + auto objC = Node::create(); + { + Vector array1; + Vector array2; + + // push back objA 3 times + array1.pushBack(objA); // retain count is 2 + array1.pushBack(objA); // retain count is 3 + array1.pushBack(objA); // retain count is 4 + + array2.pushBack(objA); // retain count is 5 + array2.pushBack(objB); + array2.pushBack(objC); + + for (auto obj : array1) { + array2.eraseObject(obj); + } + CCASSERT(objA->getReferenceCount() == 4, ""); + } + CCASSERT(objA->getReferenceCount() == 1, ""); + + { + Vector array1; + // push back objA 3 times + array1.pushBack(objA); // retain count is 2 + array1.pushBack(objA); // retain count is 3 + array1.pushBack(objA); // retain count is 4 + CCASSERT(objA->getReferenceCount() == 4, ""); + array1.eraseObject(objA, true); // Remove all occurrences in the Vector. + CCASSERT(objA->getReferenceCount() == 1, ""); + + array1.pushBack(objA); // retain count is 2 + array1.pushBack(objA); // retain count is 3 + array1.pushBack(objA); // retain count is 4 + + array1.eraseObject(objA, false); + CCASSERT(objA->getReferenceCount() == 3, ""); // Only remove the first occurrence in the Vector. + } // Check the retain count in vec7 CCASSERT(vec7.size() == 20, "");