How to save Objects to File (AS3 / Air) - actionscript-3

What I want?
Save my Project in a Editor created with Air Application
What is to save?
1 Object -> Type ArrayCollection -> Contains -> Objects from own classes...
What was my first try?
var stream :FileStream = new FileStream();
stream.writeObject(myArrayCollection);
What was the Problem?
The objects inside of myArrayCollection got this Structure:
public class MyClass1
{
public var title:String;
public var description:String;
public var kindOf:String = "...";
public var thumbnail:String;
public var children:ArrayCollection
...}
Every public var were saved by the FileStream.... works fine
Inside the children arrayCollection are objects from this class:
public class MyClass2 extends XMLDocument implements IExternalizable
{
public const kindOf:String = "Seite";
[Bindable]
public var title:String;
public var contenBox:OwnClass; //extended spark Group
public function get childrens():ArrayCollection
{
var childs: ArrayCollection = new ArrayCollection();
var i:int = 0;
while(i > (contenBox.container as spark.components.Group).numElements)
{
childs.addItem((contenBox.container as spark.components.Group).getElementAt(i));
i--;
}
return childs;
}
public function readExternal(input:IDataInput):void
{
trace("hello i'am reading");
}
public function writeExternal(output:IDataOutput):void
{
trace("hello i'am writing");
output.writeObject(children);
}
Now the Problem... the fileStream contains my MyClass2 objects with the var "title" but there is no children ArrayCollection... the console don't shows the traces :-/

Have you tried serializing your Object? You could serialize it to XML and than back again on reading.
It seems a good library for this is Flexxb
other way would to write the file as raw binaries with Bytearray as was explained here
hope it helps!

Related

converting class name and passing to another class

I have a function where I receive map as Class, everything works fine, but when I convert it to string, where map is something like 'IconNorth', convert it to "FieldNorth" and try to pass to another class constructor I get error.
public function newMap(map, x1:int, y1:int):void {
var createMap = new map();
list.push(createMap);
addChild(createMap);
var field = map.toString().split("Icon").join("Field");
new Board(this[field]);
}
and the Board class
public class Board extends MovieClip {
public static var list:Array = new Array();
public function Board(field=null) {
list.push(this);
if (field!=null) {
addChild(new field());
}
}
...
the error is
ReferenceError: Error #1069: Property [class FieldNorth] not found on Map and there is no default value.
I also tried 'getDefinitionByName' but it gives similar error.
So how do I convert a class name with or without using string to another class name and pass it to constructor?
First, you'll need to get the full class, so you can't just use CLass.toString() - in your case that would produce the string: "[class FieldNorth]"
Use getQualifiedClassName to get the full string class:
var classStr:String = flash.utils.getQualifiedClassName(map);
Then, to get the reverse, you'll have to use getDefinitionByName:
var myClass:Class = flash.utils.getDefinitionByName(classStr) as Class
var inst = new myClass();
So, for your example, this is what your code should look like:
public function newMap(map:Class, x1:int, y1:int):void {
var createMap:Object = new map();
list.push(createMap);
addChild(createMap);
var fieldClassStr:String = flash.utils.getQualifiedClassName(map).replace("Icon","Field");
try { //if getDefinitionByName fails, it will throw an exception, not return null
var field:Class = flash.utils.getDefinitionByName(fieldClassStr) as Class
new Board(field);
}catch(e:Error){}
}
public function Board(field:Class) {
list.push(this);
addChild(new field());
}

AS3 - Error #1009: Cannot access a property or method of a null object reference

I have no idea what is causing the error. I'm sure its very obvious.
(See comments below).
package src.main{
import src.tilespack.Tile;
public class Main{
public var tile:Tile;
public function Main{
var t:Tile = Tile.tiles[0]; //Error here
trace(Tile); //This will also cause an error
}
Tile:
package src.tilespack{
public static var tiles:Array = [];
public static var floorTile:Tile = new FloorTile(0); //Causes an error in FloorTile Class
public var bitmapData:BitmapData;
public function Tile(bitmapData:BitmapData, ID:int)
{
this.ID = ID;
tiles[ID] = this;
this.bitmapData = bitmapData;
}
}
FloorTile:
package src.tilespack{
import src.gfx.Assets;
import src.tilespack.Tile;
public class FloorTile extends Tile{ //Error here
public function FloorTile(ID:int){
super(Assets.floorTileData, ID);
}
}
}
Error #1009: Cannot access a property or method of a null object
reference.
I've noticed few problems in your code:
1) The file Tile doesn't have a definition of class. Probably, this is just a typo, but anyway, this file should look something like:
package src.tilespack
{
public class Tile
{
public static var tiles:Array = [];
public static var floorTile:Tile = new FloorTile(0); //Causes an error in FloorTile Class
public var ID:int;
public var bitmapData:BitmapData;
public function Tile(bitmapData:BitmapData, ID:int)
{
this.ID = ID;
tiles[ID] = this;
this.bitmapData = bitmapData;
}
}
}
2) Your code has something like "recursive linkage" (sorry, I don't know the official term). Your class Tile has the static variable floorTile, and it tries to create an instance of the FloorTile class, which itself extends the class Tile.
So we have a situation, when the class Tile tries to use the class FloorTile (because static variables should be instantiated during the first class use), and the class FloorTile tries to use the class Tile. And it's a problem.
You may either remove static variable of the type FloorTile or change code of the class Tile to prevent usage of the class FloorTile before the class Tile is prepared to work. Here an example of the second approach:
package src.tilespack
{
import flash.display.BitmapData;
public class Tile
{
public static var tiles:Array = [];
private static var _floorTile:Tile;
public static function get floorTile():Tile
{
if (!Tile._floorTile)
{
Tile._floorTile = new FloorTile(0);
}
return Tile._floorTile;
}
public var ID:int;
public var bitmapData:BitmapData;
public function Tile(bitmapData:BitmapData, ID:int)
{
this.ID = ID;
tiles[ID] = this;
this.bitmapData = bitmapData;
}
}
}

Unable to clone vector with deep copy of objects

This is my vector that I want to fully clone (meaning that if I change the cloned vector it doesn't affect the original vector).
var vector:Vector.<Path_Tiles> = new Vector.<Path_Tiles>();
vector = path_finder.Find_Path(Gird.TILE_SET, start, end, R_G_B, SCAREDNESS);// return a vector of path_tiles in order
and I'm trying to put it into this vector
var vector2:Vector.<Path_Tiles> = clone(vector);
and clone method is this (which I found this method on a website so I do not fully understand it)
public function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
But I'm getting this error: "[Fault] exception, information=TypeError: Error #1034: Type Coercion failed: cannot convert AS3.vec::Vector.#85973d1 to AS3.vec.Vector.."
How do I convert Path_Tiles into an object?
Assure your Path_Tiles class has been registered:
flash.net.registerClassAlias("tld.domain.package.Path_Tiles", Path_Tiles);
Then, you may copy by serializing the data to a ByteArray:
var tiles:Vector.<Path_Tiles>;
var tilesCloned:Vector.<Path_Tiles>;
var byteArray = new ByteArray();
byteArray.writeObject(tiles);
byteArray.position = 0;
tilesCloned = byteArray.readObject() as Vector.<Path_Tiles>;
Cast the readObject() deserialization to Vector.<Path_Tiles> using the as keyword.
Constructors for objects serialized must accept default parameters.
To put this all together, say this was your Path_Tiles class:
Path_Tiles.as
package
{
public class Path_Tiles
{
public function Path_Tiles(property1:String=null, property2:int=undefined) {
this.property1 = property1;
this.property2 = property2;
}
public var property1:String;
public var property2:int;
}
}
Here is your main class, showing an example of deep cloning the Path_Tiles collection:
Main.as
package
{
import flash.display.Sprite;
import flash.net.registerClassAlias;
import flash.utils.ByteArray;
public class Main extends Sprite
{
public function Main() {
super();
var source:Vector.<Path_Tiles> = new <Path_Tiles>[
new Path_Tiles("Hello", 1),
new Path_Tiles("World", 2)
];
var cloned:Vector.<Path_Tiles> = clone(source);
}
public function clone(source:Vector.<Path_Tiles>):Vector.<Path_Tiles> {
flash.net.registerClassAlias("Path_Tiles", Path_Tiles);
var byteArray = new ByteArray();
byteArray.writeObject(source);
byteArray.position = 0;
return byteArray.readObject() as Vector.<Path_Tiles>;
}
}
}
Finally, we can see the object was deep copied; confirmed by memory address:

I can't seem to get a object to pull another variable object when the class is created?

I am trying to create two var one var is a object that gets another object inside the same class
package plus1
{
public class ScreenInfo
{
//setting a button to 0 means that it is disabled
public var object:Object = { button1:_Object2 };
public var _Object2:Object = { name:"test name" };
public function ScreenInfo()
{
}
}
}
but ever time i do this
var screens:ScreenInfo = new ScreenInfo();
var obj:Object = screens.object["button1"]
the object is null why is this shouldn't it pass me the second object?
Because you are using variable initializers, you can't safely use references to other members. How do you know that _Object2 exists when you create object ?
I suggest you move the instantiation of object in the constructor of your class :
public var object:Object;
public var _Object2:Object = { name:"test name" };
public function ScreenInfo(){
this.object = {button1:_Object2};
}

AS3 public variable won't store values

first time poster here.
So I'm building a "multi-RSS feed reader" and I've broken this into 2 classes, a "TechFeed.as" and a "Feed.as"; The tech feed instantiates multiple feeds by passing URL's to a new Feed object.
My issue at the moment is that in the Feed.as I have a couple public variables which are used in TechFeed.as to display basic details about the feed, however, these variables refuse to retain any value I give them within Feed.as's functions, and are turning up "null".
Edit: Also maybe something to note; TechFeed.as is the main AS file the stage uses.
TechFeed.as
package {
import flash.display.MovieClip;
public class TechFeed extends MovieClip {
private var feed_one:Feed = new Feed("http://feeds.feedburner.com/crunchgear");
private var feed_two:Feed = new Feed("http://feeds.mashable.com/Mashable");
private var feed_three:Feed = new Feed("http://www.engadget.com/rss.xml");
public function TechFeed() {
trace(feed_one.feed_title);
//feed_name.text = feed_one.getFeedTitle();
}
}
}
Feed.as
package {
import flash.net.URLLoader;
import flash.events.Event;
import flash.net.URLRequest;
public class Feed {
//Public variables to display feed info
public var feed_title:XMLList;
public var feed_desc:String;
public var feed_link:String;
//Setting up variables which help load the feeds
private var feedXML:XML;
//Create a loader to load an external URL
private var loader:URLLoader = new URLLoader();
public function Feed(inURL:String = "") {
//Load the xml document
loader.load(new URLRequest(inURL));
loader.addEventListener(Event.COMPLETE,onLoaded);
}
//When the loader had loaded the xml document, pass that into a variable for use.
private function onLoaded(e:Event):void {
feedXML = new XML(e.target.data);
// break down the xml document elements into singular XML array lists
//Feed details
this.feed_title = feedXML.channel.title;
this.feed_link = feedXML.channel.link;
this.feed_desc = feedXML.channel.description;
trace(this.feed_title);
}
}
}
Any help will be greatly appreciated :)
Thanks,
Geoff
Your problem is timing you are trying to write the data from the feed before it is returned from the server.
In this example I assign a function to call back on when the data is loaded.
package {
import flash.display.MovieClip;
public class TechFeed extends MovieClip {
private var feed_one:Feed;
private var feed_two:Feed;
private var feed_three:Feed;
public function TechFeed() {
feed_one= new Feed("http://feeds.feedburner.com/crunchgear",assignResults);
feed_two= new Feed("http://feeds.mashable.com/Mashable",assignResults);
feed_three= new Feed("http://www.engadget.com/rss.xml",assignResults);
}
public function assignResults(value:value):void{
feed_name.text = value;
}
}
}
package {
import flash.net.URLLoader;
import flash.events.Event;
import flash.net.URLRequest;
public class Feed {
//Public variables to display feed info
public var feed_title:XMLList;
public var feed_desc:String;
public var feed_link:String;
//Setting up variables which help load the feeds
private var feedXML:XML;
//Create a loader to load an external URL
private var loader:URLLoader = new URLLoader();
private var _callBackFunc:Function;
public function Feed(inURL:String = "", callBackFunc:Function) {
this._callBackFunc = callBackFunc;
//Load the xml document
loader.load(new URLRequest(inURL));
loader.addEventListener(Event.COMPLETE,onLoaded);
}
//When the loader had loaded the xml document, pass that into a variable for use.
private function onLoaded(e:Event):void {
feedXML = new XML(e.target.data);
// break down the xml document elements into singular XML array lists
//Feed details
this.feed_title = feedXML.channel.title;
this.feed_link = feedXML.channel.link;
this.feed_desc = feedXML.channel.description;
this._callBackFunc(this.feed_title);
}
}
}
If the problem is that feed_one.feed_title is coming up null in the TechFeed() ctor, that is because you are not waiting for the feed to finish loading.
What you aught to do is dispatch an event from the Feed when it is done loading and processing the data, catch it in TechFeed and then use the public variables as you please (this also means that your Feed class will have to subclass EventDispatcher):
In Feed class:
private function onLoaded(e:Event):void {
feedXML = new XML(e.target.data);
// break down the xml document elements into singular XML array lists
//Feed details
this.feed_title = feedXML.channel.title;
this.feed_link = feedXML.channel.link;
this.feed_desc = feedXML.channel.description;
trace(this.feed_title);
dispatchEvent(new Event(Event.COMPLETE));////Dispatch Event
}
In TechFeed class:
public function TechFeed() {
trace(feed_one.feed_title);//This will trace "null"
feed_one.addEventListener(Event.COMPLETE, dataLoaded);//add event listener
}
private function dataLoaded(e:Event):void{
var feed = Feed(e.currentTarget);
feed.removeEventListener(Event.COMPLETE, dataLoaded);//remove event listener to prevent memory leaks
trace(feed.feed_title);// This will trace the correct title
}