Flex: ObjectUtil.copy() throws errors for classes with custom namespace properties.
The easiest way to clone an instance of a class in Flex is to use the inbuilt ObjectUtil.copy() . This function serialises the entire object into an array of bytes and then deserialises it back into a completely new instance of that class. All that needs to be added to a class to ensure that it is correctly deserialised is to include the [RemoteClass] metadata tag above the class definition.
Rather than explaining it all here, I suggest you have a read of Darron Schall’s explanation of it here.
I’ve used this method for cloning custom objects in several projects without issue, but when I implemented this functionality in a current project, everytime I called ObjectUtil.copy() I received the following error:
ArgumentError: Error #2004: One of the parameters is invalid.
at flash.utils::ByteArray/writeObject()
There is only one parameter for ObjectUtil.copy() – the object to be copied, so obviously there was something in one of my classes that didn’t like being deserialised. Unfortunately by this time there was already a reasonable inheritance chain going in my classes, and eventually I had to start stripping bits out of my classes (and superclasses) until the error went away.
It turns out that the culprit was a custom namespace property in my superclass. Whenever the namespace was defined, ByteArray.writeObject() fails to deserialise the byte array, and the copy fails.
package
{
[RemoteClass]
public class Example
{
public var ns:Namespace = new Namespace("http://www.misprintt.net");
public function Example()
{
}
}
}
Cloning an instance of this class will always throw an error:
var example:Example();= new Example(); var o:Object = ObjectUtil.copy(example);
Luckily the solution is also describe in Darron’s post. While he doesn’t indentify what problems he was having, he explains how he used the [Transient] metadata tag to avoid issues with ObjectUtil.copy().
So now that the culprit has been identified, it is just a matter of adding the [Transient] metadata tag to avoid the namespace being serialised in the first place.
package
{
[RemoteClass]
public class Example
{
[Transient]
public var ns:Namespace = new Namespace("http://www.misprintt.net");
public function Example()
{
}
}
}
Anyway, hopefully this saves some time for those trying to decipher yet another one of those vague flash player errors :)
