以下是该方案:
我们拥有一个在Flash CS5.5中运行的创意团队,并生成包含图形元素和动作脚本代码的SWF资产,以及一个创建.as文件并构建“代码SWF”的工程团队。代码SWF文件必须加载或嵌入广告素材资源,并与其中的代码进行交互,以使我们的应用能够正常运行。
对于iOS移动开发,还有另一个考虑因素 - 由于Apple TOS,无法在iOS的AIR应用程序包中加载运行时代码(请参阅related question)。因此,无法使用Loader在iOS环境中加载SWF并保留其代码。
将SWF嵌入到ActionScript文件中的标准方法会导致Loader直接将嵌入的SWF作为字节加载。这导致访问顶级主时间轴,如下所示:
[Embed(source="embed_test.swf")]
private var no_aot_support:Class;
public function main():void
{
var no_ios:* = new no_aot_support();
addChild(no_ios);
no_ios.addEventListener(Event.COMPLETE, function():void {
var timeline:MovieClip = no_ios.getChildAt(0).getChildAt(0);
trace(timeline.foo); // foo variable exists, output is 'blah'
});
}
但是,这种嵌入机制在iOS设备上不起作用,因为每个Apple的TOS都不允许运行时代码 - 所有代码必须在编译时通过提前编译器(AOTCompiler)和SWF传递以这种方式嵌入不符合此标准。
询问周围,我found可以使用类级嵌入来解决这个问题,因为类级嵌入确实会通过编译器并导致在iOS下运行代码:
package
{
import flash.display.MovieClip;
[Embed(source="embed_test.swf", symbol="Symbol1")]
public final dynamic class anim extends MovieClip { };
}
这很好用,但是我不想在SWF中引用一个符号,我想要整个swf(也就是引用主时间轴),但是下面会导致编译错误:
package
{
import flash.display.MovieClip;
[Embed(source="embed_test.swf")]
public final dynamic class anim extends MovieClip { };
}
我还反编译了SWF,找到了主时间轴符号,并尝试了这个:
package
{
import flash.display.MovieClip;
[Embed(source="embed_test.swf", symbol="embed_test_fla.MainTimeline")]
public final dynamic class anim extends MovieClip { };
}
但是编译器坚持认为这个符号不存在。
由于我有很多很多SWF资产,我需要一个不涉及改变整个工作流程的解决方案(即进入每个FLA并进行更改)。这应该是可能的,如果没有,这是Adobe应该解决的工作流问题。
所以在这里我被困 - 常规嵌入获得MainTimeline但在iOS中不起作用,类级嵌入在iOS中工作并且无法访问MainTimeline。
随意download my expample project并玩这个。
答案 0 :(得分:5)
在主时间轴上放置对象始终会在SWF文件中生成生成的代码:Flash IDE会为应用程序生成所有必需的代码,也就是说,它会创建文档类的实例在运行时放在舞台上。但是,这是无法访问的代码,除非通过加载器对象加载SWF - 既不使用[嵌入],也不生成SWC将允许它。
我已尝试导出SWC,因为像@ 32bitkid我认为这是一种绕过限制的方法。事实证明,你可以实例化文档类,即使你没有显式声明它并让IDE自动生成它。但是,所有舞台实例都消失了。 :(你也可以声明一个自定义文档类,并使用addChild()
将你的库对象放在舞台上 - 然后一切正常。但是你在IDE的主时间轴上做的任何事情,你都无法访问永远。
这也是有道理的:对象实际上是放置在主时间轴实例上的阶段实例。但是一旦你打电话给new MyDocumentClass()
,你就会创建一个新实例 - 它还没有任何成员。
奇怪的是,所有这些对于任何库对象都应该是正确的 - 将对象实例放置在库对象时间线中也应该需要代码生成,不应该吗? - 但它实际上并不完全相同:当您调用new MyLibraryObject();
时,您在库对象中放置在舞台上的任何内容仍然存在并且可以访问。
因此。我看到你的项目工作的唯一方法是让你的设计师在每个FLA的库中创建一个唯一命名的“时间轴”MovieClip(或Sprite),并导出为ActionScript。 (您不能总是使用“时间轴”,因为在使用多个SWC时会出现命名冲突)然后使用此“时间轴”将任何必要的对象直接放在舞台上,添加帧代码等。在其中,设计人员可以完全按照他们习惯的方式工作,除了设备硬件和可用的API之外没有任何限制。唯一真正的区别是FLA本身的主时间轴上根本不存在任何东西。
然后,您可以使用SWC方法(这比手动生成[嵌入]代码要简单得多)并在主应用程序中实例化“时间轴”符号 - 一切都应该在您需要的地方。
答案 1 :(得分:0)
我正在发布我自己的解决方案来解决这个问题,以防这个问题发生:
此处有更详细的回复:Is it possible to embed or load SWFs when making iphone apps (Is it allowed by Apple)
我已经创建了一个工具来解决此问题,方法是将嵌入式SWF合并到主SWF中。通过这种方式,嵌入是AOT编译并转换为objective-c代码,因此我获得了我的资产实例(主时间轴),并且资产的代码被正确交叉编译以在iOS设备上工作。
它使用这样的嵌入工作:
[Embed(source="GameLevel.swf")]
private var GameLevel:Class;
public function main():void
{
var my_level:* = new GameLevel();
addChild(my_level);
}
在这种情况下,如果gameLevel.swf中包含代码,它通常在iOS中不起作用,因为新的gameLevel()会创建一个Loader并解释SWF字节码。但是,如果您首先通过我的名为SWFMerge的工具运行上述SWF,它将采用您的嵌入式SWF并将其合并到您的根SWF中。然后ADT会将你的主swf(包括嵌入代码)编译成objective-C,它将在iOS上工作,并注意:new gameLevel()现在直接在你的资产实例中产生 - 而不是一个Loader。
SWFMerge工具在此处:
http://www.onetacoshort.com/temp/SWFMerge_alpha.swf
如果此解决方法适合您或您遇到问题,请在评论中告诉我。
我将补充一点,使用SWC工作流程更好并得到官方支持,但是如果您没有原始FLA源文件,或者只是想快速使用包含代码的现有资产,这种解决方法很有用它们。