Archive for 8月, 2009
以下のような書き方はFlexならではなのかなーということで記述。
XML内の記述方法だけを見れば、いろいろ見るけど、それを同じソース内で利用するのあまり知らないので、
なるほどと思う方もいるかもしれない。(私は思った。)
フォームなどの画面から入力されたデータを1つの変数にまとめるのに、XMLを利用できる。
<mx:Model id="user">
<user>
<name>{f_name.text}</name>
<age>{f_age.text}</age>
<pref>{f_pref.text}</pref>
</user>
</mx:Model>
<mx:TextInput id="f_name" />
のようにXML中に{f_name.text}のように変数をバインディングしておき、
それをXMLのオブジェクト1つとして扱う。
1つのまとめておけば、Validatorなども作りやすくなるだろうし、
また、このようにXMLでワンクッション置いていると、入力方法の変更もしやすくなるだろう。
やっぱり、ActionScriptの非同期処理はいろいろと面倒で、なんかいい方法はないかなーといろいろと考えているが、
なんかのサブクラスを作って、それで処理をするってのはどうもお手軽ではない。。。
(これはこれで本格的にやらなくてはいけないときにはいいのですが、やっぱりちょっとしたことをするのにサブクラスは気がひけますから・・・)
それで、
1)Bの処理はAが終わったら処理をする。
2)Cの処理はAが終わったら処理をする。
ここまでは、とくに非同期処理があっても面倒ではないのです。
ところが、
3)Dの処理はBとCの処理が終わったら処理をする。
ってのがあると、、、、んんん・・・・って考えてしまいます。
そこで、こんなことができるようにとクラスを作成してみました。
ポリシーは、
・書き方が簡単であること
・サブクラスなど複雑な構造にならないこと
ってな感じで、
書き方はこんな感じです。
var flow:JobFlow = new JobFlow();
foo.addEventListener(eventName,execA);
// 処理Bは処理Aが終わってから・・・
// 第1引数が、処理したいFunction, 第2以降は依存
flow.addDependsListener(execB,execA);
flow.addDependsListener(execC,execA);
flow.addDependsListener(execD,execB,execC);
// この関数がexecAを呼び出すと仮定している・・
foo.execute();
private function execA(e:Event):void{
// 自分のメソッド内の最後で自分のメソッドが終わったことを通知する
flow.doneDepend(execA);
}
private function execB():void{
// たとえば、処理Bがさらに非同期処理の結果を待つ場合
foo.addEventListener(eventName,handleExecB);
}
private funciton handleExecB(e:Event):void{
// このように実際に終わったときに依存が終了したことを伝える
foo.doneDepend(execB);
}
private function execC():void{
flow.doneDepend(execC);
}
private function execD():void{
flow.doneDepend(execD);
}
とこのようにすれば新たなクラスを作らなくて済むし、ちょっとした部分で非同期処理のスパゲティを回避できるのではないだろうか?
ここで、依存は関数にしたがとくに何であっても問題ない。
(関数にしたのは、コードヘルパが補完してくれるので間違いが起こりにくいので、それがいいと思っています。)
ただし、イベントの結果の中身で判断しなくてはないらない場合には、そのために関数を作るのも変ですし、
flow.addDependsListener(execD,"FLAG_A","FLAG_B");
のように記述もでき、
flow.doneDepend("FLAG_A");
のように書くこともできます。
ちなみに、今まで処理が途中までやったけど、一度何もなかったことにしたい・・・という場合は
flow.reset();
としてください。
ただし、依存関係を消すということはできません。(この場合にはインスタンスを作りなおしてね)
ソースはこちらから
たとえば、こんなXMLがある。
-
<office :document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:ooo="http://openoffice.org/2004/office" office:version="1.2">
-
</office><office :meta>
-
<meta :creation-date>2009-08-11T09:32:05</meta>
-
<dc :date>2009-08-11T09:35:06.48</dc>
-
<meta :editing-duration>PT00H03M08S</meta>
-
<meta :editing-cycles>2</meta>
-
<meta :generator>OpenOffice.org/3.0$Win32 OpenOffice.org_project/300m9$Build-9358</meta>
-
<dc :description>これはOpenOfficeのドキュメントです。</dc>
-
<meta :keyword>OpenOffice</meta>
-
<meta :keyword>XML</meta>
-
<meta :keyword>操作</meta>
-
<dc :subject>サブジェクト</dc>
-
<dc :title>これはタイトル</dc>
-
<meta :document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="13" meta:word-count="665" meta:character-count="1725"/>
-
<meta :user-defined meta:name="Info 1"/>
-
<meta :user-defined meta:name="Info 2"/>
-
<meta :user-defined meta:name="Info 3"/>
-
<meta :user-defined meta:name="Info 4"/>
-
</office>
これは、OpenOfficeで作ったドキュメントファイル(odt)ファイルのから取り出したmeta.xmlだ。
通常、名前空間がなければ
var metas:XMLList = _xml.title;
のようにすればよい。
しかし、名前空間があるXMLの場合には、この名前空間を指定しなければいけない。
では、<dc:title />のように名前空間がある要素の取得は以下のようにする。
var _dcNS:Namespace = _xml.namespace("dc");
trace(_xml.dcNS::title); // これで「これはタイトル」の文字列が出力される
初めの例でいえば、_xml.title の title が _dcNS::title のようにNamespaceの変数名 + "::" + 要素名 にすればいいのだ。
これが、もっと深い子になると、非常に読みづらくなる。
(※:_xmlは上の内容のXMLオブジェクトです。)
16進数をソースコード上に直接記述するには、
var code:int = 0xff;
のように0xと付ければよい。
では、8進数はといえば、実はActionScript3 では直接記述する方法はないようです。
ただし、
var num:int = 0766;
のように記述してもこれは、8進数ではなく、10進数の766です。
したがって、8進数を入力したい場合には
var num1:int = parseInt("0766",8);
// もしくは
var num2:int = parseInt("766",8);
のように記述する必要があるというわけです。
頭に"0"をつけるのは好き好きで可能です。
また、16進数でparseIntを使うと
var num1:int = parseInt("1f6",16);
var num2:int = parseInt("0x1f6",16);
で問題ない。
ただし、
var i:int = parseInt("790",8);
のように、8進数ではありえない数字[9]があってもエラーにはならなく、
この結果は「7」となってしまうようです。
同様に、n進数はparseInt(number,n)の基数nを変えればいいということです。
では、次に与えられた数字を16進数や、8進数ではどのようになるのだろうか?ということを求めるにはどうしたらいいだろうか?
これは、非常に簡単だ。
var num:int = 504; trace(num.toString(16)); // 16進数 -- 1f8 trace(num.toString(8)); // 8進数 -- 770 trace(num.toString(2)); // 2進数 -- 111111000
となる。
このような関数は知らなくても、簡単に作れてしまうために調べる手間より作ってしまえと思ってしまうことがあるが、
やっぱり他の人が見ることがあることを考えると標準を使うほうがよいだろう。
散々今まで作ってきたAIRでのZIP解凍&圧縮ライブラリですが、
ソースとドキュメントを公開しました。
ライセンスはLGPLとなっています。
これでZIP関連はまあ、ひと段落ついたので今度はメール関連を作っていきます。

