Question

I've got a stack of images. Those images are all added to a sprite container:

var container:Sprite = new Sprite();
container.addChild(img);//added in a loop
addChild(container);

Later, when I iterate through the container to remove the images I say:

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

Only a part of the images are removed. If I trace container.numChildren I get the correct number of images to be removed. Did someone have the same problem ?

Was it helpful?

Solution

I've encountered this problem as well. What's actually wrong here is that you're stepping up through the display list AND cutting it down with each iteration. In AVM2 the display list depth is automatically managed in this context, and when you remove a child the rest of the display list depth is adjusted. Anyway, the solution is to wrap it up in a while loop:

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

Update

Also one note about your code. Try not to cast a new reference to the clip. This will cause issues for the garbage collection process in the flash VM, which is automated and only objects dereferenced or referenced using weak references will be cleaned up. So you can do one of the following:

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

or

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

OTHER TIPS

Try removing them in reverse order. It's possible that your're missing removals because you're trying to remove them while in a forward-bound loop.

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

This code will work :

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

However I wanted to point out what is wrong with that loop so you understand what is happening. Add the trace I've added to your code below, into your code. :

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

You'll see that each time through the loop the number of children decreases as expected.

But what you need to understand is that when a child is removed -- the display list of the container changes in a very significant way.

Here's an example of how your display list might look before running the loop -- the number I have on the front of these is their position on the container display list.

0-cat
1-dog
2-bird
3-cow
4-elephant
5-clown

Now, the first time through the loop, you remove cat cause it's location is 0 on the display list. Here's what the display list looks like now :

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

Notice that the display list indexes have shifted based on the removed child. There CANNOT be gaps on the display list by design.

so, the next time through the loop, the value of i is 1 -- right ? That means "bird" will be removed from the display list, as opposed to dog, which is what you might have expected.

so here's the display list after that next time through the loop :

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

So, yes. Many of these solutions will work. In this case I'd recommend the while loop. But I think the real knowledge to be gained from this question is understanding the problem.

Similar to @Michael's answer, your original code is missing removals because your "numChildren" size is reducing and your iterator is increasing on every loop:

As @Ascension Systems noted, this is the best approach.

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

However if you do want to do it in a loop, you'll need to do it in reverse.

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

To illustrate what happens in your original code, note the following example with 25 children:

If you remove in a forward loop this is what happens (on each iteration):

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...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top