网创优客建站品牌官网
为成都网站建设公司企业提供高品质网站建设
热线:028-86922220
成都专业网站建设公司

定制建站费用3500元

符合中小企业对网站设计、功能常规化式的企业展示型网站建设

成都品牌网站建设

品牌网站建设费用6000元

本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...

成都商城网站建设

商城网站建设费用8000元

商城网站建设因基本功能的需求不同费用上面也有很大的差别...

成都微信网站建设

手机微信网站建站3000元

手机微信网站开发、微信官网、微信商城网站...

建站知识

当前位置:首页 > 建站知识

坑爹的CCARRAY_FOREACH

第一次使用CCARRAY_FOREACH遍历一个CCArray数组并且删除数组里的东西时发生出乎意料的结果:
类似代码如下:

创新互联公司坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都网站设计、成都网站建设、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的会泽网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!

CCArray *children = this->getChildren();
CCObject *temp = NULL;CCARRAY_FOREACH(children, temp)
{
    CCSprite *sprite = dynamic_cast(temp);
    if(sprite->getTag() == 1)
    {
        this->removeChild(sprite);
    }
}



这段代码执行下来,发现有些Tag为1的精灵没有被删除,为了查原因,我追查到CCARRAY_FOREACH宏的定义中:

#define CCARRAY_FOREACH(__array__, __object__)                                                                         \
    if ((__array__) && (__array__)->data->num > 0)                                                                     \
    for(CCObject** __arr__ = (__array__)->data->arr, **__end__ = (__array__)->data->arr + (__array__)->data->num-1;    \
    __arr__ <= __end__ && (((__object__) = *__arr__) != NULL/* || true*/);                                             \
    __arr__++)


如果在我原来的代码中展开CCARRAY_FOREACH宏的话,代码为如下形式:

if ((children && children->data->num > 0)
    for(CCObject** __arr__ = children->data->arr, **__end__= children->data->arr + children->data->num-a;
         __arr__ <= __end__ && (((temp) = *__arr__) != NULL);
         __arr__++)
{
    CCSprite *sprite = dynamic_cast(temp);
    if(sprite->getTag() == 1)
    {
        this->removeChild(sprite);
    }
}


然后追踪到void CCNode::removeChild(CCNode* child)->

void CCNode::removeChild(CCNode* child, bool cleanup)->

void CCNode::detachChild(CCNode *child, bool doCleanup)->

最后定位到detachChild中的m_pChildren->removeObject(child);是关键

m_pChildren是一个CCNode中的一个CCArray类型变量,CCArray中调用removeObjectsInArray又调用了ccArray类中的ccArrayRemoveArray函数,

最终定位到ccArrayRemoveObjectAtIndex中的memmove((void *)&arr->arr[index], (void *)&arr->arr[index+1], remaining * sizeof(CCObject*));

memmove函数中把CCArray中当前要删的那个项删掉,然后后面的项往前移动,所以当有两个连续的项Tag为1的精灵为A、B,并且当前的__arr__指向A精灵,当把当前__arr__指向的精灵(A精灵)删掉后,同时也执行了把后面B精灵往前移动了,所以本轮循环结束后,执行__arr__++后,__arr__指向的是B精灵后面的精灵的地址,所以B精灵成为了漏网之鱼。

结论:不要在CCARRAY_FOREACH遍历CCArray时删除里面存的对象。但是可以用CCARRAY_FOREACH_REVERSE宏,因为这个宏是从后面遍历的。


文章标题:坑爹的CCARRAY_FOREACH
转载注明:http://bjjierui.cn/article/jgpcsd.html

其他资讯