Врожденная ошибка Flash с getChildIndex

У меня есть этот код, который работает отлично, но иногда — всякий раз, когда Flash так думает — он падает. Вот полученный отладочный текст:

Ошибка №2025

показатьрезультат: правда

тележка = 10

Долли добавила

Добавлены универсальные чипы

Подсветка SH:[object SurfaceElement]10-[object TSprite]-vex!

ArgumentError: Ошибка № 2025

Обратите внимание, что "досада!" — это имя объекта vex, который является TSprite (=Sprite).

    public function update(players:Array, showResult:Boolean = false):void {
        try {
            var debug:String = "showResult:" + showResult.toString() + "\n";
            debug += "dolly = " + dolly.toString();

            // RESET columns
            columns.length = 0;
            billboards.removeAllChildren();
            var column:ChipColumn;

            // add dolly
            var alfa:Number = 1;
            if (showResult) {
                column = getChipColumn(vex.getChildIndex(numberToSH[dolly]));
                column.addChild(dollySpr);
                alfa = LOSER_ALPHA; // fade-out (non-animated) non-winning columns
            }

            debug += "\nDolly added";

            for (var k:* in players) {
                var player:Player = players[k];
                var bets:Array = player.getBets();
                for (var i:* in bets) {

                    // is there a column already for these chips?
                    column = getChipColumn(i);
                    column.alpha = alfa; // loser..?
                    for (var j:int = bets[i]; j > 0; --j) {
                        var bmp:TBitmap = new TBitmap(chips[k], Align.CENTER, Align.CENTER);
                        bmp.y = - column.numChildren * 5;
                        column.addChild(bmp);
                    }
                }
            }

            debug += "\nGeneric Chips added";

            if (showResult) {
                var shs:Array = SurfaceElement.NumberToAllSH[dolly];
                for each (var sh:SurfaceElement in shs) {
                    debug += "\nHighlighting SH:" + String(sh);
                    debug += sh.corresponds.toString();
                    debug += "-" + String(sh.parent);
                    debug += "-" + String(sh.parent.name);

                    column = getChipColumn(vex.getChildIndex(sh)); // ERROR LINE ?!?
                    column.alpha = 1; // restore alpha
                    column.filters = [new GlowFilter(0xffffff, 1, 12, 12, 3, 3)];
                }
            }

            debug += "\nEnd of Highlighting !!!!!!";

            // sort columns by y
            var sorted:Array = columns.sortOn("sortY", Array.NUMERIC | Array.RETURNINDEXEDARRAY);
            debug += "\n" + sorted.toString();
            for (i in sorted) {
                column = columns[sorted[i]];
                if (!column) break; // pointers to undefined data have arrived (put last)
                billboards.addChild(column);
            }
            debug += "\nEnd of ALL";
        } catch(e:Error) {
            if (!Debug.field.text.length) {
                Debug.field.textColor = 0xffffff;
                Debug.field.appendText(e.message + "\n" + debug + "\n" + e.toString());
            }
        }
    }

    private function getChipColumn(i:int):ChipColumn {
        var column:ChipColumn = columns[i];
        if (!column) {
            column = new ChipColumn();

            // calc column properties
            var sh:SurfaceElement = vex.getChildAt(i) as SurfaceElement;
            var point:Point = sh.getCenterProjected();
            point = billboards.globalToLocal(point);

            column.sortY = sh.center.y;
            column.x = point.x;
            column.y = point.y;
            columns[i] = column;
        }
        return column;
    }

Из текста отладки очевидно, что здесь происходит ошибка:

debug += "\nHighlighting SH:" + String(sh);
debug += sh.corresponds.toString();
debug += "-" + String(sh.parent);
debug += "-" + String(sh.parent.name);
column = getChipColumn(vex.getChildIndex(sh)); // ERROR LINE ?!?

Ошибка 2025 возникает, когда getChildIndex вызывается для не дочернего объекта. Но sh ЯВЛЯЕТСЯ дочерним элементом досады, как следует из имени родителя (досада!). И есть только ОДИН раздражение.

Еще одна особенность заключается в том, что сообщение об ошибке (e.message) просто выдает: Error 2025, в то время как ошибка в строку (e.toString()) выдает: ArgumentError: Error #2025

Разве это не должно быть больше похоже на:

ArgumentError: Ошибка № 2025: Предоставленный DisplayObject должен быть дочерним по отношению к вызывающему объекту ??


person Bill Kotsias    schedule 01.06.2013    source источник
comment
В нем будет сказано, что если вы запустите его в проигрывателе отладки и увидите полную трассировку стека либо во всплывающем окне, либо в консоли (в зависимости от того, как вы его запускаете. Похоже, ваша проблема в том, что у вас есть статический метод, который возвращает все ваши shs, и я был бы готов поспорить, что ваш код каким-то образом проскальзывает в sh, который либо больше не находится в списке отображения, либо принадлежит другому родителю, возможно, даже другому экземпляру, у которого есть то же имя Посмотрите в отладчике адрес памяти родителя по сравнению с текущим vex.   -  person Amy Blankenship    schedule 02.06.2013
comment
Ну да, я мог бы также проверить, если parent == vex, не нужно смотреть на шестнадцатеричные адреса. Я сделаю и опубликую свои результаты здесь   -  person Bill Kotsias    schedule 02.06.2013
comment
Ну да, ты был прав. Я создавал новый vex, но статический массив: var shs:Array = SurfaceElement.NumberToAllSH[dolly]; содержал ссылки на старые SurfaceElements, которые принадлежали старому vex. Нужно следить за статическими ссылками, они не уничтожаются, если вы не делаете это вручную... Вы можете превратить свой комментарий в ответ, чтобы я мог его наградить.   -  person Bill Kotsias    schedule 03.06.2013


Ответы (1)


Статическое глобальное состояние — это плохая вещь. В этом случае у вас нет возможности узнать, имеют ли объекты sh, которые вы извлекаете из своего статического массива, какое-либо отношение к текущему объекту "vex" или нет.

Вместо того, чтобы SurfaceElement отслеживать все свои экземпляры, которые были добавлены, подумайте о том, чтобы ваш класс Vex выставлял массив surfaceElements (или, что еще лучше, вектор). Если они построены на сцене (я подозреваю, что вы отслеживаете их статически, потому что у вас нет хорошей «ручки» для работы с объектами временной шкалы/сцены), вы можете сделать что-то вроде этого в своем конструкторе:

public var surfaceElements:Array = [];
function Vex() {
    super();
    var loops:int = numChildren;
    for (var i:int=0; i<loops; i++) {
       var surface:SurfaceElement = getChildAt(i) as SurfaceElement;
       if (surface) {
          surfaceElements[surfaceElements.length] = surface;
       }
    }
}

Затем, когда вы закончите с этим конкретным Vex, вы также закончите с его поверхностными элементами без пересечения.

person Amy Blankenship    schedule 03.06.2013