ここでの問題の根本は、インスタンスMovieClipをSharedObjectに保存しようとしていることです。MovieClipは(フラッシュにネイティブな)組み込みオブジェクトであるため、保存可能な形式に変換することはできません。これにより、フラッシュはデータをディスクに保存される汎用オブジェクトに変換します。この時点でSharedObjectに何が入っているかを正確に推測することしかできません。
flashはgetPeople()呼び出しで共有オブジェクトを実際にロードせず、すでにメモリ内にあるオブジェクトを使用するだけなので、初めて機能するようです。2回目の実行時に、アプリはディスクからジェネリックオブジェクトを読み取り、ジェネリックオブジェクトを作成します。
フラッシュプレーヤーがオブジェクトを読み取るときにコンストラクターにデータを渡すことを知らないという別の問題があります。
いくつかの可能な回避策があり、いくつかは次のとおりです。
- データをテキストとして保存する
- データをByteArrayとして保存します
- 「データオブジェクト」にデータを保存する
これらはそれぞれ、読み取りおよび書き込みプロセス中に変換が必要ですが、これはインターフェイスを使用して簡略化できます。これにより、オブジェクトが変更された場合でも、SharedObjectのデータを読み取ることができるという柔軟性が追加されます。
1:テキスト
例として、オブジェクトに2つのメソッドを追加し、それらをととPerson
呼ぶことができます。このメソッドは、共有オブジェクトに格納できるテキストを返します。はテキストを解析し、オブジェクトの値を入力します。serialise()
deserialise()
serialise()
deserialise()
これを説明するためのサンプルを次に示します。
class Person {
private var name:String;
private var age:int;
public function serialise():String {
return [name, age].join("\t");
}
public function deserialise(input:String):void {
var tokens:Array = input.split("\t");
name = tokens[0];
age = parseInt(tokens[1]);
}
public static function create(name:String, age:int):Person
{
var output:Person = new Person();
output.name = name;
output.age = age;
return output;
}
}
使いやすさのために、人々のコレクションを管理するためのクラスを作成できます。
class People {
private var people:Vector.<Person> = new Vector.<Person>();
public function clear():void {
people.splice(0, people.length);
}
public function add(person:Person):void {
people.push(person);
}
public function serialise():String {
var output:Array = [];
for each (var person:Person in people)
output.push(person.serialise());
return output.join("\n");
}
public function deserialise(input:String):void {
var tokens:Array = input.split("\n");
for each (var token:String in tokens) {
var person:Person = new Person();
person.deserialise(token);
add(person);
}
}
public function save():void {
var so:SharedObject = SharedObject.getLocal("cookie");
so.data.people = serialise();
so.flush();
}
public function load():void
{
var so:SharedObject = SharedObject.getLocal("cookie");
if (so.data.people != null)
deserialise(so.data.people);
}
}
使用法:
var people:People = new People();
people.load();
trace(people.serialise());
people.clear();
people.add(Person.create("Candy", 21));
people.add(Person.create("Sandy", 23));
people.add(Person.create("Randy", 27));
people.save();
trace(people.serialise());
この例の明らかな欠陥は、\n文字と\t文字をデータの一部として(つまり、人の名前として)使用できないことです。これは、テキストデータの一般的な欠点です。
**更新:組み込みのJSONメソッドを調べて、テキストとの間でオブジェクトをシリアル化するための一貫したアプローチを確認してください。
2:ByteArray
上記のテキストメソッドと非常によく似ていますが、serialise / deserialiseメソッドは、オブジェクトが書き込むByteArrayの追加パラメーターを受け入れる点が異なります。次に、ByteArrayが保存され、共有オブジェクトからロードされます。この方法の利点は、結果のデータが通常、テキスト方法よりもコンパクトで用途が広いことです。
Flashは、ここで使用できるIDataInputおよびIDataOutputインターフェイスも定義します。
3:データオブジェクト
それでもオブジェクトを直接保存したい場合は、データを運ぶという唯一の目的を果たすプロキシオブジェクトを作成できます。データオブジェクト(別名DO)は、メソッドではなく変数のみを持つオブジェクトです。例えば:
class PersonDO {
public var name:String;
}
次のように使用されます。
var person2:Person;
var person3:Person;
var person4:Person;
var thePeople:Array=[];
var so:SharedObject;
function init():void{
person1 = new Person("james");
person2 = new Person("mike");
// store the people data into data objects
person1DO = new PersonDO();
person1DO.name = person1.name;
person2DO = new PersonDO();
person2DO.name = person2.name;
thePeople.push(person1DO,person2DO);
savePeople();
// load the people into data objects
getPeople();
person1 = new Person(thePeople[0].name);
person2 = new Person(thePeople[1].name);
private function savePeople():void{
so = SharedObject.getLocal("savedData");
if(so.data.thePeopleArray == null){
so.data.thePeopleArray = thePeople;
so.flush();
}
}
private function getPeople():void{
so = SharedObject.getLocal("savedData");
var thePeeps:Array = so.data.thePeopleArray;
trace(thePeeps);
}
これは他の方法よりも単純に見えるかもしれませんが、オブジェクトを直接保存することには欠点があります。-保存されたデータは非常に壊れやすい-オブジェクトを変更すると、各オブジェクトのバージョンが複数ない限り、データは使用できなくなります。-データオブジェクトへの参照がアプリケーションにコンパイルされていることを確認する必要があります。-共有オブジェクトの一般的な使用シナリオは、あるSWFからデータオブジェクトを保存し、それらを別のSWFにロードすることです。両方のSWFが、保存およびロードされるクラスの同一バージョンを使用していることを確認する必要があります。
お役に立てば幸いです。