DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 16.2 Adding Data to a Client-Side Shared Object

16.2.1 Problem

You want to add data to a client-side shared object (whether it be a remote or local shared object).

16.2.2 Solution

Add the values as properties of the shared object's data object.

16.2.3 Discussion

Shared objects have a special built-in property named data. The data property is an object to which you should add any information that you want to save to the shared object:

// Store a username value to the shared object.
mySO.data.username = "Joey";

Properties attached directly to the shared object, rather than to its data property, are not written to the shared object. Thus, attaching properties directly to the shared object is useful only for data that does not need to persist between sessions. Therefore, the following code is potentially an erroneous attempt to save data:

mySO.someVal = "this value is lost when the movie closes";

The correct approach is to attach the value to the data property, as follows:

mySO.data.someVal = "this value is stored in the shared object";

You can store several native ActionScript datatypes to the shared object's data property, as follows.

mySO.data.myArray = new Array("a", "b", "c");
mySO.data.myDate = new Date(  );

However, you cannot store movie clips, buttons, text fields, or shared objects themselves to a shared object's data property such that the data persists correctly between sessions.

You can also store objects created from custom classes to a shared object's data property. However, for the object to be properly cast (interpreted as the intended datatype) when it is retrieved in the next session, you must use the Object.registerClass( ) method. If you do not register your custom class, ActionScript won't know what to do with the data retrieved from the shared object.

The conventional use of the registerClass( ) method is to associate a class to a symbol in the Library. You should do this when you want to develop components with class definitions. However, you can also use the registerClass( ) method to register a class to an arbitrary identifier:

function MyClass (  ) {} 

Object.registerClass("MyClassID", MyClass);

This code tricks the object into storing information about the class that created it. Therefore, when the data is retrieved from the shared object, Flash knows what kind of object it is.

The custom class must be defined and registered in all movies that retrieve the custom object data from a shared object.

There is one additional consideration you must address to successfully recast custom datatypes when they are retrieved from a shared object. When an object is retrieved from a shared object, all the properties are set and then the constructor for the class is called. This process will likely wipe out some, if not all, of the properties of the object if your constructor includes any initialization functionality. To understand this potential problem, consider the following example:

// Define a custom class. The constructor sets a property in the new object.
function MyClass(val) {
  this.val = val;
}

// Register the class.
Object.registerClass("MyClassID", MyClass);

// Create or open a local shared object.
my_l_so = SharedObject.getLocal("myFirstLSO");

// If the shared object doesn't already have an objA object, create a new MyClass 
// object and assign it to the shared object. Otherwise, if objA already exists
// (meaning that it was saved from a previous session), display the value of its val 
// property in the Output window.
if (my_l_so.data.objA == undefined) {
  my_l_so.data.objA = new MyClass("yay");
  my_l_so.flush(  );
} else {
  trace(my_l_so.data.objA.val);
}

In this example, the value of the object's val property is always undefined. The reason is that even though the object was initially saved with the value "yay", the constructor is called with an undefined value each time the shared object data is retrieved. You can solve this problem by enclosing all the initialization code within the constructor in an if statement, as follows, which prevents the property from being erroneously reinitialized:

function MyClass(val) {
  if (!this.inited) {
    this.inited = true;
    this.val = val;
  }
}

When you change the constructor in this way, the original value for val is retained. When the MyClass object is first created, the inited property does not exist. Therefore, the if statement's condition is true. However, when the object is retrieved from the shared object, the inited property is true, and the initialization code does not execute. In this way the val property is not overwritten.

16.2.4 See Also

Recipe 16.3, Recipe 16.10, and Recipe 17.2

    [ Team LiB ] Previous Section Next Section