A very interesting thing I noticed a while ago is the behavior of SharedObjects when the data in them is an object as well. The idea is that when you add any Object to the data field of a SharedObject instance this is not cloned and is passed by reference. So from then on, any changes to the Object will be reflected in the SharedObject data.
If you want to prevent this behaviour it's best that you create clones of the object and asign them to the SharedObject.
Bellow I added a Flex example to prove it. The first time you run the program below, it will show the current date because there's nothing in the SO. From the second run onward it is showing the 78 Date although that change is never flushed.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
private function init():void
{
var so : SharedObject = SharedObject.getLocal("someTest");
//Initialize with the current date or the date in the Shared Object
var someDate: Date = new Date();
if (so.data.thedate != null) someDate = so.data.thedate as Date;
//show the date in the UI
theDate.data = someDate;
//put it in the shared object and force write it to disk
so.data.thedate = someDate;
so.flush();
//the changes done to the object are stored in the shared object
someDate.setFullYear(1978, 4, 2);
}
]]>
</mx:Script>
<mx:DateField id="theDate" width="100%" height="100%" />
</mx:Application>
| 1. | <?xml version="1.0" encoding="utf-8"?> |
| 2. | <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()"> |
| 3. | <mx:Script> |
| 4. | <![CDATA[ |
| 5. | private function init():void |
| 6. | { |
| 7. | var so : SharedObject = SharedObject.getLocal("someTest"); |
| 8. | //Initialize with the current date or the date in the Shared Object |
| 9. | var someDate: Date = new Date(); |
| 10. | if (so.data.thedate != null) someDate = so.data.thedate as Date; |
| 11. | //show the date in the UI |
| 12. | theDate.data = someDate; |
| 13. | //put it in the shared object and force write it to disk |
| 14. | so.data.thedate = someDate; |
| 15. | so.flush(); |
| 16. | //the changes done to the object are stored in the shared object |
| 17. | someDate.setFullYear(1978, 4, 2); |
| 18. | } |
| 19. | ]]> |
| 20. | </mx:Script> |
| 21. | <mx:DateField id="theDate" width="100%" height="100%" /> |
| 22. | </mx:Application> |
| 23. |
My friend Iacob showed me an interesting livedocs comment on the Performing Object Introspection page. It seems that if you try to change values while you are in a for loop, everything kind of gets messed up.
For example take the following code :
For instance:
var obj : Object = {};
obj.a = "x";
obj.b = "y";
obj.c = "z";
for(var key:String in obj){
obj[key] = obj[key]+"x";
trace(key+"="+obj[key]);
}| 1. | var obj : Object = {}; |
| 2. | obj.a = "x"; |
| 3. | obj.b = "y"; |
| 4. | obj.c = "z"; |
| 5. | for(var key:String in obj){ |
| 6. | obj[key] = obj[key]+"x"; |
| 7. | trace(key+"="+obj[key]); |
| 8. | } |
produces:
a=xx
a=xx
c=zx
The most interesting thing I found is that you can use the new Object() instead of {} and it works fine.
If you do another for right after that and just trace the output you see that properties a and c were affected (and show once) while property b was not affected by the previous for (not changed).
Weird, but as I said, you can use new Object() instead of the curly brackets {} to get rid of this problem.