Actionscript 3 can';t删除精灵容器的所有图像

Actionscript 3 can';t删除精灵容器的所有图像,actionscript-3,loops,sprite,removechild,Actionscript 3,Loops,Sprite,Removechild,我有一堆图像。 这些图像都添加到精灵容器中: var container:Sprite = new Sprite(); container.addChild(img);//added in a loop addChild(container); 稍后,当我遍历容器以删除图像时,我会说: for(var i:int=0;i<container.numChildren;i++) { var currImg:Sprite = container.getChildAt(i) as Sp

我有一堆图像。 这些图像都添加到精灵容器中:

var container:Sprite = new Sprite();
container.addChild(img);//added in a loop
addChild(container);
稍后,当我遍历容器以删除图像时,我会说:

for(var i:int=0;i<container.numChildren;i++)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}

for(var i:int=0;i尝试以相反的顺序删除它们。可能是因为您在前向绑定循环中尝试删除它们而丢失了删除

for(var i:int=container.numChildren;i>=0;i--)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}

我也遇到过这个问题。这里的实际错误是,您正在逐步增加显示列表,并在每次迭代时将其减少。在AVM2中,显示列表深度在此上下文中自动管理,当您删除一个子项时,显示列表的其余深度将进行调整。无论如何,解决方案是将其打包在while循环中:

while(container.numChildren > 0){
    container.removeChildAt(0);
}
更新

还有一个关于代码的注意事项。请尝试不要强制转换对片段的新引用。这将导致flash VM中的垃圾收集过程出现问题,该过程是自动的,只有使用弱引用取消引用或引用的对象才会被清除。因此,您可以执行以下操作之一:

for(var i:int=0;i<container.numChildren;i++)
{
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
     currImg = null;
}
for(var i:int=0;i此代码将工作:

while(container.numChildren > 0)
{
    container.removeChildAt(0);
}
但是,我想指出该循环的错误,以便您了解发生了什么。将我添加到下面代码中的跟踪添加到您的代码中:

for(var i:int=0;i<container.numChildren;i++)
{
     trace (i + " : " + container.numChildren);
     var currImg:Sprite = container.getChildAt(i) as Sprite;
     container.removeChild(currImg);
}
现在,第一次通过循环,您删除了cat,因为它在显示列表中的位置是0。下面是显示列表现在的样子:

0-dog
1-bird
2-cow
3-elephant
4-clown
请注意,显示列表索引已根据删除的子项进行了移动。按设计,显示列表上不能有间隙

所以,下一次通过循环时,i的值是1——对吗?这意味着“bird”将从显示列表中删除,而不是dog,这是您可能期望的

下面是下一次循环之后的显示列表:

0-dog
1-cow
2-elephant
3-clown

所以,是的。这些解决方案中的许多都会奏效。在这种情况下,我建议使用while循环。但我认为从这个问题中获得的真正知识是理解问题。

与@Michael的答案类似,您的原始代码缺少删除,因为您的“numChildren”每个循环的大小都在减小,迭代器也在增加:

正如@Ascension Systems所指出的,这是最好的方法

while(container.numChildren > 0){
  container.removeChildAt(0);
}
但是,如果您确实希望在循环中执行,则需要反向执行

for(var i:int=container.numChildren;i>=0;i--){
  container.removeChild(container.getChildAt(i));
}
为了说明在原始代码中发生的情况,请注意以下带有25个子项的示例:

如果在正向循环中删除,则会发生以下情况(在每次迭代中):


另一件事是关于人们发布的代码+您自己的代码。在for循环中,您正在循环中强制转换变量“i”。尝试避免这种情况。在循环外强制转换int,以便您可以访问for循环外范围内的“i”,并在运行循环后使引用无效(也就是说,在使用for循环的情况下。while循环不需要这个)。如果将getChildAt(i)更改为getChildAt(0),则for循环可以工作@是的,使用
0
是可行的,但是如果你这样做了,你就不用迭代器
i
做任何事情,因此你最好使用while循环。i正在计算长度,所以它正在被使用。我有点担心这是公认的答案;尽管更正了关于取消对Spr的引用的部分在循环体中避免垃圾收集问题的方法是绝对的piffle;引用是封闭函数的局部引用,因此在方法体的末尾会超出范围-向循环中添加这样的代码只是增加了噪音!最后,您确实应该按相反的顺序删除子级(numChildren->0)为了避免显示列表必须随着循环的每次迭代而崩溃。这正是他的问题,当他删除索引0处的子项时,索引1处的子项将移动到索引0,然后在循环的下一次迭代中,他删除索引1处的子项,将子项保留在索引处0@The_asman是的,但是如果你从最高的数字开始删除它们r,然后降到0,所有的元素都将被删除(包括第0个位置的元素)。试试看。是的,我同意你的观点,这就是为什么我+1 lol只是指出了他失败的原因。@阿斯曼(啊,我误读了你的评论。)如果你不习惯用数字访问集合中的元素,那么很容易错过。
while(container.numChildren > 0){
  container.removeChildAt(0);
}
for(var i:int=container.numChildren;i>=0;i--){
  container.removeChild(container.getChildAt(i));
}
i:0 Array length:24
i:1 Array length:23
i:2 Array length:22
i:3 Array length:21
i:4 Array length:20
i:5 Array length:19
i:6 Array length:18
i:7 Array length:17
i:8 Array length:16
i:9 Array length:15
i:10 Array length:14
i:11 Array length:13
//the remaining 12 items never get looped over...