ActionScript 3 - Библиотеки скриптов

Я пытаюсь загрузить полученный swf сборки swc вручную. Из-за моей конкретной среды нам необходимо разделить определения классов на swcs (где это имеет смысл), чтобы удалить избыточный код из выходных файлов swf.

Вкратце, я определяю класс (LibA) в SWF, который я создаю с помощью compc. Я компилирую его как в формат swc, так и в формат каталогов, поэтому я могу легко извлечь library.swf из каталога для загрузки во время выполнения (внешняя связь) и использовать swc для компиляции из любого swf, созданного с помощью Flash CS5 или mxmlc.

LibA.as:

package
{
    public class LibA
    {
        public function LibA()
        {
            trace("*** LibA()");
        }
    }
}

Main.as:

package
{
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;

    public class Main extends Sprite
    {
        private var self:Main;
        private var context:LoaderContext;

        public function Main()
        {
            var l:Loader = new Loader();
            self = this;

            l.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event) {
                self.addChild(l.content);

                var liba:LibA = new LibA();
            });
            l.load(new URLRequest("./libs/build/liba.swf"));
        }
    }
}

Я создаю swc / каталог swc с помощью

compc -output libs/build/liba.swc -include-sources libs/LibA.as -debug=true

и я установил соответствующую привязку в настройках AS3 в Flash CS5 при создании Main (класс, связанный непосредственно со сценой).

Все публикуется без проблем.

Однако во время выполнения я получаю VerifyError: Error #1014: Class LibA could not be found.

Что мне здесь не хватает? Я хочу иметь возможность загружать и использовать классы, определенные в liba.swf из моего Main.swf.

Полный дамп трассировки:

verify Function/<anonymous>()
                        stack:
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  0:getlex 4
                        stack: Main?
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  2:getlex 7
                        stack: Main? flash.display::Loader?
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  4:getproperty content
                        stack: Main? flash.display::DisplayObject?
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  6:callpropvoid addChild 1
                        stack:
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  9:findpropstrict LibA
                        stack: Object
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  11:constructprop 10 0
                        stack: *
                        scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ Main$ Main Main] 
                         locals: Object flash.events::Event? * 
  14:coerce LibA
VerifyError: Error #1014: Class LibA could not be found.

person Demian Brecht    schedule 16.01.2012    source источник
comment
Когда возникает ошибка сразу после запуска или даже после загрузки внешнего SWF?   -  person turbosqel    schedule 17.01.2012
comment
В этом примере он создается при создании экземпляра класса.   -  person Demian Brecht    schedule 17.01.2012
comment
Итак, вы загружаете внешний SWF в неправильный домен приложения, если основное приложение не может получить к нему доступ. Как ты загружаешь liba.swf, используешь LoaderContext?   -  person turbosqel    schedule 17.01.2012
comment
@turbosqel: Нет, нет LoaderContext. В этом контексте (без каламбура;)) я не думаю, что это имеет значение, поскольку это не веб-интерфейс. По сути, он запускается локально из Flash Player (сторонняя реализация виртуальной машины).   -  person Demian Brecht    schedule 17.01.2012
comment
@turbosqel: Я должен добавить, однако, что я пытался использовать LoaderContext, и это не имело значения (хотя, возможно, я сделал что-то не так).   -  person Demian Brecht    schedule 17.01.2012
comment
попробуйте загрузить с 'новым LoaderContext (false, ApplicationDomain.currentDomain);' , это может помочь.   -  person turbosqel    schedule 17.01.2012
comment
@turbosqel: Пожалуйста, добавьте свой комментарий в качестве ответа, чтобы его приняли. Это устранило мою проблему. Очевидно, я неправильно конструировал LoaderContext, когда пробовал его в последний раз. Спасибо.   -  person Demian Brecht    schedule 18.01.2012


Ответы (2)


Если вы хотите загрузить классы из SWF, вам нужно сделать что-то вроде (в обработчике событий):

var li:LoaderInfo = e.target as LoaderInfo; // get the loaderInfo object from the event
var swf:MovieClip = li.loader.content as MovieClip; // get the swf
var c:Class = swf.loaderInfo.applicationDomain.getDefinition( "LibA" ) as Class; // get the class definition for LibA

Создание нового c должно дать вам ваш LibA объект. Вам понадобится полное определение класса в качестве имени.

Если я понимаю, что вы пытаетесь сделать, я почти уверен, что вы можете настроить SWC для встраивания внешней библиотеки - то есть вы получаете завершение кода, но ни один из классов не включен, и SWC ищется во время выполнения.

ИЗМЕНИТЬ

Просто попробовал что-то вроде того, что вы делаете. В моем примере выше, когда вы создаете c, если вы его отслеживаете, он будет отслеживать LibA. Однако, если вы явно укажете на него, вы получите описанную вами ошибку. Я думаю, это связано с тем, что Flash путается с двумя определениями LibA - одним, на который была сделана ссылка, и тем, который вы загружаете - они находятся в двух разных доменах приложений.

Исправление таково, как описывает его @turbosqel, загрузите его с помощью объекта LoaderContext:

var l:Loader = new Loader();
var context:LoaderContext = new LoaderContext( false, ApplicationDomain.currentDomain );
l.contentLoaderInfo.addEventListener(Event.COMPLETE, this._onLoadComplete );
l.load(new URLRequest("./libs/build/liba.swf"), context);

У меня это работает, теперь я могу явно ссылаться на класс LibA.

person divillysausages    schedule 17.01.2012
comment
Ваше предположение верное, и вот что делается (привязка установлена ​​на внешнюю, и я вручную загружаю swf, содержащий определение класса). Забавно, но это работает, как и ожидалось, в используемой мной сторонней среде выполнения, но не во Flash. Мой полный вариант использования на самом деле немного сложнее, поскольку я представляю наследование, определяемое cross-swc (т.е. LibB extends LibA). - person Demian Brecht; 17.01.2012
comment
см. новую правку - она ​​работает с моей стороны. Также, реквизит для @turbosqel - person divillysausages; 17.01.2012
comment
Да, это исправило это для меня. Если @turbosqel не добавит ответа (поскольку он сначала предложил исправление), я приму его - спасибо за помощь. - person Demian Brecht; 18.01.2012
comment
Я ожидаю, что это будет проблемой, потому что вам нужно загружать классы в тот же домен приложения, если вам нужны классы в cross-swf. Когда вы загружаете swf, читающий классы из родительского, это может быть дочерний домен. Для получения дополнительной информации прочтите о RSL. - person turbosqel; 19.01.2012

liba не существует, пока ваш SWF не будет загружен, потому что вы не импортируете его в main.

Это означает, что во время компиляции его нет

Переместите var liba:LibA = new LibA(); в вызов функции в загруженном корне swf и вызовите функцию после загрузки e.currentTarget.someFunc

person The_asMan    schedule 17.01.2012
comment
На самом деле он не должен присутствовать во время компиляции с использованием определений swc. - person Demian Brecht; 17.01.2012
comment
Если вы попытаетесь создать экземпляр класса, его необходимо импортировать. Именно поэтому вы получаете VerifyError: Ошибка № 1014: не найден класс LibA. И так же, как turbosqel предложил использовать LoaderContext. - person The_asMan; 17.01.2012