Jesse lives and works in Melbourne Australia. He is the Cofounder and a Director of http://ActionScript.org. A Flash enthusiast, teacher, author, freelancer and speaker Jesse enjoys participating in the http://ActionScript.org community and the wider Flash scene when he has time. Another of the great new features of Flash MX is the SharedObject. A SharedObject in the most basic sense is a contraption designed to allow local storage of data pertinent to a user on that user's system. Like a cookie but better. If you can't think of any good reason to store data on a user's drive, you're not thinking hard enough. As an example, you could use a SharedObject (SO henceforth) to determine if a user has already visited your site - perhaps allowing them to automatically skip the intro animation after the first time. There are plenty of more complicated and cooler applications also.
The first thing to note about SOs in Flash is that they can be disabled on the client side. This will obviously thwart all our cool applications of them so straight off, here's some code to check if SOs are enabled on a user's system:
[as]function checkSO() {
// Does this client allow sharedobjects to be stored?
// Create a dummy SO and try to store it
mySO = SharedObject.getLocal("test");
if (!mySO.flush(1)) {
// SOs not allowed on this system!
// Prompt user to change settings
System.showSettings(1);
} else {
// SOs allowed
trace("Your system allows sharedobjects");
}
}
checkSO();[/as]
Don't fret, I've never been one to throw you in the deep end, but that code is important to begin with. Dump it on a keyframe in a new Flash MX movie and run it to be sure your system supports and allows SOs before we begin. (Also note that the above code only checks if your system supports SOs of 1 byte, so if you want to adapt it for any use other than checking whether the feature is on or off, keep that in mind.)
Let's get down to business with a whirlwind revision of what an Object is. An Object is a way to store (generally related) data in a nicely categorized fashion. So if we have 100 customers, instead of using:
[as]Cust1Name = "Joe";
Cust1Age = 20;
Cust1Pet = "Dog";
Cust2Name = "Mary";
Cust2Age = 19;
Cust2Pet = "Dog";
...[/as]
We object oriented programmers use:
[as]Cust1 = new Object();
Cust1.name = "Joe";
Cust1.age = 20;
Cust1.pet = "Dog";
...[/as]
To create a new SharedObject we use:
[as]mySO = SharedObject.getLocal("test");[/as]
This is also the code we use to load up a previously saved SO. Here, "mySO" is the Object name we will refer to the SO by within Flash, while "test" is the file name it will be given on the system. SOs are stored locally with a ".sol" extension by default. Note that the file name field may contain forward slashes but most other special characters are not allowed, including ~ % & ; : " ' , < > ? # and spaces.
At any point after having created your SO, provided you have not deleted it, you can write it to the user's disk using the flush method, which returns true, false or "pending". A Boolean return value of true indicates that the write operation was approved and successful while false indicates the opposite. We will deal with a "pending" return value in a moment. The physical file on the disk is not created/altered until the flush method is invoked.
[as]mySO = SharedObject.getLocal("test");
mySo.data.name = "Joes";
success = mySO.flush();[/as]

Figure 1.1 The Local Storage Reuqest Prompt
The new event model allows us to trigger a function when a value is returned from the flush method. The function defined via SharedObject.onStatus is triggered after a flush operation which requests extra space is resolved. Note that this function is not triggered while a flush operation remains pending (awaiting a user's authorization to write to the disk for instance), nor is it triggered when a flush operation can be completed immediately within the existing space confines set by the user. So if my client allows 10k to be written to their disk and I attempt to write 1k, the onStatus function will not be invoked. When invoked, the function is passed an object indicating the success or failure of the operation. Macromedia's docs suggest the object contains a class property and a code property however from my tests I've found it actually includes a level property in place of the class property. A successful request for additional allocation returns an object with a level property set to the string "status" and a code property of "SharedObject.Flush.Success" while an unsuccessful request returns a level property of "error" and a code of "SharedObject.Flush.Failed". Implementing a function which checks the return value of onStatus allows us to successfully determine whether or not our write operation proceeded:
[as]mySO = SharedObject.getLocal("test");
mySo.data.name = "Joes";
success = mySO.flush(100000);
if (success == "pending") {
mySO.onStatus = function(result) {
if (result.code == "SharedObject.Flush.Success") {
trace("Sucess writing to disk");
writeSuccess = true;
} else {
trace("Failure writing to disk");
writeSuccess = false;
}
};
} else {
writeSuccess = success;
}[/as]
When we add data to our SO we specify that we want it to be stored long term on the user's disk by adding it to the 'data' child. Adding information elsewhere makes it expendable. Also note that only SOs with properties in the data child will actually be written to the disk, my tests have shown a SO with an empty data child is not saved.
The following code creates a new SO, saves it, deletes it, then reloads it. The for..in loop then traces all the values it found in the reloaded version. Note that the shortLived variable, which was not part of the data child is no longer present, while the stickAround variable is. Also note that the variables preserve their data types; we don't have to convert numbers from their string saved form back into numbers as we used to with cookies.
[as]// Create an SO
mySO = SharedObject.getLocal("test");
// Add some expendible data
mySO.shortLived = "Woe is me, the short lived variable";
// Add some important data
mySO.data.stickAround = "I'll be here for years to come!";
mySO.data.num = 123;
mySO.data.obj = new Array(4, 5, 6, 7);
// Write the SO to the disk (I'm not checking for success here)
mySO.flush();
// Delete the SO
delete mySO;
// Load the SO back in
mySO = SharedObject.getLocal("test");
// Scan the SO for values
for (a in mySO.data) {
trace(a+": "+mySO.data[a]);
}[/as]
An interesting thing to note is that when you reload a previously written SO, change a value or two and re-write it, the original file's contents isn't exactly overwritten. Instead the new additions are merged with the old file, overwriting any previous definitions but retaining values which weren't altered. You can see it in action by trying out this code:
[as]// Create an SO
mySO = SharedObject.getLocal("test");
// Add some important data
mySO.data.stickAround = "I'll be here for years to come!";
// Write the SO to the disk (I'm not checking for success here)
mySO.flush();
// Delete the SO
delete mySO;
// Reload the SO
mySO = SharedObject.getLocal("test");
// This time we're not adding any data, so when we write
// our SOit should the old data be overwritten, right?
mySO.flush();
// Delete the SO
delete mySO;
// Load the SO back in once more,
mySO = SharedObject.getLocal("test");
// Scan the SO for values
for (a in mySO.data) {
trace(a+": "+mySO.data[a]);
}
// Wrong! The trace shows our old values all still exist![/as]
[as]mySO = SharedObject.getLocal("test");
mySO.data.stickAround = "I'll be here for years to come!";
mySO.flush();
delete mySO;
// Reload the SO
mySO = SharedObject.getLocal("test");
delete mySO.data.stickAround;
mySO.flush();
// Delete the SO
delete mySO;
// Load the SO back in once more,
mySO = SharedObject.getLocal("test");
// Scan the SO for values
for (a in mySO.data) {
trace(a+": "+mySO.data[a]);
}
// Wohoo! No stickAround value![/as]
Macromedia's docs don't show us how to remove the physical file from a user's drive, (although they say it's possible), but we can combine two things we know already to figure it out. Firstly, when we write a SO with no properties in its data child, no file is written. Secondly when we delete a property from the data child and re-write the SO the property is removed from the file on the disk also. So in order to delete the actual file, one need only delete all the properties of the data child. This is probably best done with a for...in loop.
[as]// Make a basic SO
mySO = SharedObject.getLocal("test");
mySO.data.stickAround = "I'll be here for years to come!";
mySO.data.myArray = new Array(1, 2, 3, 4);
mySO.flush();
delete mySO;
// Reload the SO
mySO = SharedObject.getLocal("test");
for (a in mySO.data) {
delete mySO.data[a];
}
mySO.flush();
// Delete the SO
delete mySO;
// Load the SO back in once more,
mySO = SharedObject.getLocal("test");
// Scan the SO for values
for (a in mySO.data) {
trace(a+": "+mySO.data[a]);
}
// There are none. There's no file on the drive any more either[/as]
It's noteworthy that all the examples I've used in this tutorial cover creating and accessing the SO from the same SWF file. In practice this will rarely be the case, as we like to make our SWF files modular. To access a SO file created by a different SWF file you need to provide additional arguments to the getLocal() method. See this thread in which we show how it's done.
Finally, if you are determined to force your user to accept the SO you can advise them that SOs are required for your application and then run this code:
[as]System.showSettings(1);[/as]
which will popup the local settings configuration box (see Figure 2.1) and allow the user to enable/disable SO storage and increase/decrease allocated SO storage space on a general scale.

Figure 2.1 Change Local Storage Settings Prompt
Viola! That's it! Thanks to Macromedia for their good docs on this. I'm off to bed. If this tutorial helped you out please drop me an email and let me know. I'm open to corrections and suggestions as always.
| Jesse Stratford [email:jessestratford@actionscript.org] is the Co-Master of ActionScript.org and a freelance Flash developer and teacher. He is based in Australia and enjoys all things Flash. NB: If you have comments or feedback please feel free to email me, but please do not email me Flash questions; the forums are provided for that purpose and you will get a faster answer by posting you question there. |
If you have found this tutorial helpful, I hope that you will take 30 seconds to visit The Hunger Site where, with just one click you can make a free donation of food to a starving person in a third-world country. We do not benefit financially from this action; it is purely an act of charity. |
| This tutorial is protected by International Intellectual Property Rights laws and may not be reproduced or redistributed in full or part, without the prior written consent of the author. Unauthorized reproduction of this tutorial or its contents may result in prosecution. I've worked hard on this tutorial, please don't steal it. |