I am new to ActionScript and Flex.I need to learn the application developed using Flex and ActionScript.I saw an ArrayCollection declaration :
[Bindable]
public var someThing:ArrayCollection = new ArrayCollection([[]]);
What does that declaration mean.Is it multi dimensional?What is it?
This would be an ArrayCollection which is a wrapper for an Array basically to give you sort and filter function capabilities (and other methods). The constructor optionally takes an Array as an argument, [] is a new array with no elements. [[]] is an array with one element in it that is an array with no elements in it. So this is saying make a new ArrayCollection with it's source as an array which in turn contains one element that is an empty array. Not sure why they would be doing this, but that's what it does.
To sum up, you can declare and instantiate an array in AS3 like:
var myArray:Array = [];
or
var myArray:Array = new Array();
To add since this is I believe ECMAScript specific as well you can instantiate an object similarly using {}. Such as:
var myObj:Object = {};
or
var myObj:Object = new Object();
Either of these sites is good reference material for AS3:
http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7ee5.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7ee1
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html
When I first got started with Flex (having a background in HTML/JS, C, C++, and Java) I found these videos to be really useful (if not always 100% correct/up to date, they explain the overarching concepts):
http://www.adobe.com/devnet/flex/videotraining.html
Related
Summary: I create instances of various MovieClips via AS3, using MovieClip class objects that are defined in the library.
As each MC is instantiated, I push it into an array for later reference.
Finally I create an XML file that contains data related to each MC, including its name. This is the problematic part – the name has to be able to identify the respective MC when the XML is read back in. I don’t want “instance17” etc, which I assume will be meaningless in another session.
Background: I am not a career OO programmer and this is a temporary assignment, forming only a very small part of my long-term interests. It will probably be a couple of years before my next Flash project.
Create instance
Library object
Type: MovieClip, linkage _brakepipe
Instantiation
var brakepipe: _brakepipe = new _brakepipe();
shapes.push(brakepipe);
Then later
var clip: MovieClip = shapes(i);
Trace (clip);
This yields
[object _breakpipe]
So it is giving me the class name, not the MC instance name. What property or method of MC would yield “breakpipe”? (Or even "_breakpipe" - without the "object" prefix?)
You can use an associative array. It could look like this:
var shapes:Array = new Array();
and then
shapes.push({item:_brakepipe,_name:"brakepipe"};
Essentially the curly brackets create an Object instance and the name before the colon (:) is the name you create that you want associated with the value after the colon.
so now you can do this in a loop
trace(shapes[i]._name+"\n"+shapes[i].item);
// output:
// brakepipe
// [object _brakepipe]
The nice thing about this method is you can extend it for any number of properties you want to associate with your array element, like this:
shapes.push({item:_brakepipe,_name:"brakepipe",urlLink:"http://www.sierra.com",_status:"used",_flagged:"false"};
and now
shapes[i]._status
would return the string "used". And you could change that value at runtime to "new" by doing
shapes[i]._status = "new";
The Instantiation / Then later / This yields... Seems to be unclear for me, but you may try this and change the code...
Because I'm not sure not sure about the instance name you want to store...
In your loop you may do this if clip is a MovieClip! :
var clip: MovieClip = shapes(i);
clip.name = "breakpipe_" + i
trace (clip.name);
// will output : breakpipe_1 - > breakpipe_n...
You may deal with the clip.name later by removing the extra "_number" if you want.
If i == 13
var clip: MovieClip = new MovieClip();
clip.name = "breakpipe_" + 13
trace(clip.name);
// output breakpipe_13
var pattern:RegExp = /_\d*/g;
trace(clip.name.replace(pattern,""));
//output :
//breakpipe
So here, you may push your Array or Vector with the instance name.
Am I wrong?
I've an object contain all types of data
var obj1:Object={boo:true,num:0,str:"me",arr:[0,"me2",[0,1]],mc:myMc,obj:{boo:false,num:0,str:"me3",arr:[0,"me4",[0,1]]}};
when I clone this object to obj2 using ByteArray with writeObject(obj1)& readObject()properties, everything is fine except obj2.mc (mc is a variable that hold the linkage of a movie clip in the library whose class is set to myMc) can not be added to stage,
addChild(new obj2.mc)
//TypeError: Error #1007: Instantiation attempted on a non-constructor.
Help please!!
You cannot duplicate movie clips that easy. It should be something similar to:
var objectClass:Class = Object(obj2.mc).constructor;
var instance:MovieClip = new objectClass() as MovieClip;
It would be much easier if you pass a Class rather than instance. In your case, that should be myMc - the class name of the object that is in the library, right?
If so, you can simply instantiate it directly: var instance:MovieClip = new myMc();
The important think to remember is that you don't need to hold reference to an instance, but the class instead!
Guys After 2 hours of experimenting, I came out with this, This is simply the perfect solution... I changed to another way than using ByteArray, which is writing each variable in obj2 to its corresponding value in obj1, but faced another problem: when I change arrays in obj2, I found that arrays in obj1 is changed too, this means when writing variables of obj2, arrays were only referenced to that of obj1.. so I had to loop through arrays to write each value in an array individually..
var obj1:Object={mc:myMc,bo:true,num:0,str:"me",arr:[myMc,true,0,"me2",[0,1,[0,1]]],obj:{mc:myMc,bo:false,num:0,str:"me3",arr:[myMc,true,0,"me4",[0,1]]}};
var obj2:Object=clone(obj1);
function clone( source:Object ):* {
var myOBJ:Object=new Object();
for (var property in source) {
if (source[property] is Array) {
myOBJ[property]=clone(source[property]);
} else {
myOBJ[property]=source[property];
}
}
return (myOBJ);
}
Thanks for all, you've inspired me..
I am writing an iOS game in Flash and I need a way to clone polymorphic objects.
I have BaseClass, SubClass1, SubClass2 (and so on...) and I need a clone() method in BaseClass, that will create a copy of the current object, without a conditional such as
var obj:BaseClass;
if(this is SubClass1) {
obj = new SubClass1();
}else if(this is SubClass2) {
obj = new SubClass2();
}else...
I need a way to create an object and create the exact bytes (yes, a shallow copy is enough for my purpose) of the object. I've looked at:
AS3 - Clone an object
As3 Copy object
http://actionscripthowto.com/how-to-clone-objects-in-as3/
But none seem to work. Probably not available in AIR 3.3 for iOS SDK. (they compile, but the code doesn't work in my case)
Is there any other way, or did anybody achieve to clone an object in AIR for iOS?
Thanks,
Can.
Bit-by-bit cloning cannot be done with ActionScript, unless your class only contains primitive values (i.e. a simple data structure). That's what the ByteArray approach you've linked to in this question's answer is used for - but when you're dealing with complex types, especially display objects, you'll soon come to the limits (as, I gather, you have already realized).
So this more or less leaves you with two options:
Create a new object and copy all of its fields and properties.
This is the way to go if you're going to need behavior and field values, and you didn't use any drawing methods (i.e., you can not copy vector graphics this way). Creating a new class instance without knowing its exact type can be done in a generalized way using reflections, getQualifiedClassName() and getDefinitionByName() will help you there, and if you need more than just the name, describeType(). This does have limits, too, though:private fields will not be available (they don't appear in the information provided by describeType()), and in order to not run into performance problems, you will have to use some sort of cacheing. Luckily, as3commons-reflect has already solved this, so implementing the rest of what you need for a fully functional shallow copy mechanism is not too complex.
Create a new instance like this:
var newObject:* = new Type.forInstance( myObject ).clazz();
Then iterate over all accessors, variables and dynamic properties and assign the old instance's values.
I have implemented a method like this myself, for an open source framework I am working on. You can download or fork it at github. There isn't any documentation yet, but its use is as simple as writing:
var myCopy:* = shallowCopy( myObject );
I also have a copy() method there, which creates a true deep copy. This, however, has not been tested with anything but data structures (albeit large ones), so use at your own risk ;)
Create a bitmap copy.
If you do have vector graphics in place, this is often easier than recreating an image: Simply draw the content of the object's graphics to a new Bitmap.
function bitmapCopy( source:Sprite ):Bitmap {
source.cacheAsBitmap = true;
var bitmapData:BitmapData = new BitmapData( source.width, source.height, true, 0xFFFFFF );
bitmapData.draw( source, new Matrix(), null, null, null, true );
return new Bitmap( bitmapData, PixelSnapping.AUTO, true );
}
You need to create an abstract clone method in the base class and implement it for each subclass. In the specific implementations, you would copy all of the properties of the object to the new one.
public class BaseClass {
public function clone():BaseClass
{
// throw an error so you quickly see the places where you forgot to override it
throw new Error("clone() should be overridden in subclasses!");
return null;
}
}
public class Subclass1 extends BaseClass {
public override function clone():BaseClass
{
var copy:Subclass1 = new Subclass1();
copy.prop1 = prop1;
copy.prop2 = prop2;
// .. etc
return copy;
}
}
If you wanted to create a generic default implementation of clone, you could use describeType to access the properties and copy them over:
public function clone():BaseClass
{
var defn:XML = describeType(this);
var clsName:String = defn.#name;
var cls:Class = getDefinitionByName(clsName) as Class;
var inst:* = new cls();
for each(var prop:String in (defn.variable + defn.accessor.(#access == 'readwrite')).#name )
{
inst[prop] = this[prop];
}
return inst;
}
The main issue with this is that the describeType XML can get quite large - especially if you are dealing with objects that extend DisplayObject. That could use a lot of memory and be slow on iOS.
I'm using a Vector structure in ActionScript 3 to store references to a custom class. My Vector is fixed length for performance reasons, and also because it needs to map 1:1 to another data structure.
I'm trying to figure out how I "remove" an element from this fixed list. I don't want the length of the Vector to change, I just want the value of that element to be "null". Or more specifically, when I test for the truth of that element (eg: if (myVector[index]) { // do something... }), I want that test to fail for that element, since it's "empty".
So naturally, I've tried:
myVector[index] = null;
but that throws a TypeError, as does
myVector[index] = Vector.<MyClass>([]);
So what's the process for "emptying" an element of a Vector?
There must be something wrong with your index variable because
myVector[0] = null;
does not throw a TypeError when I try that. Is index an int or uint?
if you're receiving:
TypeError: Error #1009: Cannot access
a property or method of a null object
reference
than you probably haven't added your class to the object you are trying to manage (IE: you haven't added your Display objects to the stage that you are trying to nullify)
posting more code could help, but something like the following should work for you:
var spriteA:Sprite = new Sprite();
var spriteB:Sprite = new Sprite();
var spriteC:Sprite = new Sprite();
var spritesVector:Vector.<Sprite> = new <Sprite>[spriteA, spriteB, spriteC];
spritesVector.fixed = true;
trace(spritesVector); //[object Sprite],[object Sprite],[object Sprite]
spritesVector[1] = null;
trace(spritesVector); //[object Sprite],null,[object Sprite]
Should be easy. I have an object. I want to modify it, but before i do I want to save a copy of it that I can go back to. I tried setting copy = original but when i modify the attributes of the original the copy also shows the changes. I am assuming this is because in actionscript any time you assign, it really just stores a reference to the original object. So whats the best way for me to store a copy of the original object for later use?
var newObj:Object = Object(ObjectUtil.copy(oldObj));
"Copies the specified Object and returns a reference to the copy. The copy is made using a native serialization technique. This means that custom serialization will be respected during the copy.
This method is designed for copying data objects, such as elements of a collection. It is not intended for copying a UIComponent object, such as a TextInput control. If you want to create copies of specific UIComponent objects, you can create a subclass of the component and implement a clone() method, or other method to perform the copy."
http://livedocs.adobe.com/flex/3/langref/mx/utils/ObjectUtil.html#copy()
What you are looking for is a deep copy of the object rather then passing by reference. I found the answer here which uses the new ByteArray class in AS3:
http://www.kirupa.com/forum/showthread.php?p=1897368
function clone(source:Object):* {
var copier:ByteArray = new ByteArray();
copier.writeObject(source);
copier.position = 0;
return(copier.readObject());
}
Which you then use like this:
newObjectCopy = clone(originalObject);
Cheers!
// duplicate any given Object (not MCs)
Object.prototype.copy = function()
{
ASSetPropFlags(Object.prototype,["copy"],1);
var _t = new this.__proto__.constructor(this) //
for(var i in this){
_t[i] = this[i].copy()
}
return _t
};
Usage
x = ["1","2","3",[4,5],[{a:1,b:2}]]
y = x.copy()
y[0] = 0
y[3][0]="d"
trace(x)
trace(y)