|
HMDT - Back Number / January, 2001 |
January, 2001January 29, 2001■先日の修正この前、Developer Tool に付属するドキュメントには、NSString の Attribute に関する記述がない、って書いちゃったけど、実はありました。Application Kit API Reference の一番下の方に、Other Reference っていう項目があるんだ。そこに、NSAttributedString Class Cluster っていうページがあって、それが求めるドキュメントでした。だってさぁ、こんな下の方にあってさぁ、他の NSString 関係のドキュメントと全然関係ない位置にあるんだもん。言い訳でした。ごめんなさい。 January 26, 2001■文字に属性を設定するこないだのちょいネタの続きなんだけどさ、String を書くときに、属性を追加してみたよ。 属性を設定するには NSMutableAttributedString を使う。NSString のサブクラスである NSAttributedString のサブクラスだ。サブサブだ。こいつの addAtribute:value:range ってメソッドを使う:
なるほど、なるほど。じゃ、設定してみるか。えーっと value に設定するのは、、、うん?ドキュメントのどこにも書いてないぞ!?どーすんだ? しょーがないので、Web を探索。すぐ見つかる。NSAttributedString のドキュメントが置いてあった。これは、Developer Tool についてくるのとは違うらしい。どっちかってーと、こっちの方が古いような。Developer Tool のドキュメントは、不備が多いのぅ。これじゃ、デベロッパが Cocoa に移行したくても、二の足を踏むわけだ。ま、とりあえずこれによると、次のような属性を設定できるらしい。
じゃあ、使ってみるか!というわけで、一気に使ってみたのが、下の画像だ:
ひとつ注目すべきは、最後の 'fine!' かな。ここにはリガチャが設定してあるので、f と i がくっついているのが分かるだろう。ソースコードはこうなっている。解説するまでもないと思う。てきとーに読んでも分かると思うぜ!
Cocoa でのアンチエイリアシングは、なんかすげーきれいだ。アンチエイリアシングにも、いろいろな技術差があるわけね。しかし、きれいな文字で書かれるだけで、どうしてこうもやる気が起きてくるんだろう。 January 25, 2001■NSCell の中身をかく話が錯綜してごめんな、NSCell の話だ。いっけん脈絡なく見えるけど、実は壮大なこ構想に乗っとって、話題が選ばれている、ということは別にないんだ(笑)。まぁ、適当なアプリを作ろうと思った時に、ぶちあたった問題とその解決策を、かたっぱしから書き留めておいてるだけだね。 で、NSCell の話だけど、NSCell っていうのは、かなりあちこちで使われているクラスだ。たとえば、ボタンを考えてみる。ボタンは NSButton と、NSButtonCell っていうクラスからできているんだ。このとき、NSButtonCell の役割っていうのは、実際にボタンを描画することなんだ。ということは、ボタンがどう描かれるかを変えたい時は、NSButtonCell の Subclass を作ればいい、ってことらしい。 実際にはどうすればいいのか?NSCell のうちの drawInteriorWithFrame:inView: か drawWithFrame:inView: (または両方)をオーバーライドすればいい:
これらのメソッドは、引き数として cellFrame が渡されるんだ。だから、cellFrame の範囲内で、好きなものを描けばいい。例として、String を、少し左にずらして、セルの中に書くメソッドを実装してみよう:
書くべき文字列は、すでに Cell にセットしてあるものとしよう。そうすると、attributedStringValue で取り出すことができる。それを drawInRect で、書くわけだ。 これで、また一歩野望に近付いた(なんの?)。 January 25, 2001■ちょいネタ:NSString を画面にかくある文字列があったとしよう。それを画面に書くにはどうしたらいいか? AppKit の Reference の NSString Additions を見てくれ。そこにある、drawAtPoint:withAttributes: と drawInRect:withAttributes: で書くことができるんだ:
NSView にフォーカスがあたっている状態で、上のメソッドを呼び出すと、文字を書くことができるんだ。でも、これって、NSString クラスに入れるべきものなのか?なんか、変な感じ。 January 24, 2001■半透明ウィンドゥMac OS X についてくる、Clock っていうアプリケーションがあるよね。あの、半透明で表示されるアナログ時計。あれみたいな、ウィンドゥの半透明表示をやってみたいなー、って思ったんだ。 Developer Kit についてくるドキュメントを呼んだけど、記述はなし。じゃあ、っていうんで、Google で検索かけたら、あったあったありました。うーん、Google すばらしい(Google の頼もしさについてはこちらの記事も参照)。 Help With Transparent Windows これによると、NSWindow を継承させて、
という _transparency というメソッドをオーバーライドすればいいらしい。return する値は 0.0 から 1.0 の間だ。よし、さっそくやってみよう:
おぉっ、ほんとにできた!0.0 だと何も表示されなくなってしまうので、上にあげた画像は 0.5 の状態だ。 ただし、上記の文章中にもあるように、いささかトリッキーな手法だ。正規のドキュメントには記載されてないしね。将来的に使えるかどうかは分からないけど、いまのところ、これしか方法が見つからないようだ。 January 24, 2001■フェード・イン、フェード・アウトアニメーション (2):setNeedsDisplayフェード・イン、フェード・アウトアニメーションの続きだ。先日は、NSTimer から周期的にメソッドを呼び出すとこまでいったので、今日は呼び出された後からだ。呼び出された後は、View の再描画をしたい。くり返しくり返し、少しづつ変えて書くのが、アニメーションの基本だからな。で、どうするかというと、setNeedsDisplay というメソッドを使う:
これを YES とともに呼んでやると、その View は再描画をするんだ。 これで、必要な機能はそろったね。じゃ、コードを:
メソッドは 3 つ。awakeFromNib と firedByTimer と drawRect だ。 awakeFromNib でやっているのは、まず初期化。そのあと、NSTimer をスタートさせている。NSTimer で叩き起こされるのは、firedByTimer メソッドだ。 firedByTimer では、やっていることは、極めて単純。self に対して、setNeedDisplay を投げているだけだ。これによって、メッセージングシステムを経由して、drawRect が呼び出される。 drawRect では、実際に View の内容を描画している。fract の値を適当に変えて、dissolveToPoint で表示するんだ。 これで、OK!ちなみに、NSTimer を使っても、Process Viewer で見ている限りでは、プロセスは増えないようだ。気楽に使えるね。いやー、これだけでアニメーションできるとは、楽ちん極まりない。スレッドを作る必要がないぶん、Java より楽か?
January 23, 2001■サンプルコード解析(偉そー):Cocoa With Carbon or C++お宝経由で知ったんですが、ADC (Apple Developer Connection) が Mac OS X の新しいサンプルコードを公開したらしい。どうやら、Carbon コードや、C++ コードを Cocoa から呼び出すプログラムらしい。さっそくダウンロードしてみた。ダウンロード、解凍、ビルドは問題なく行えた。アプリを走らせると、次のようなウィンドウが出る:
このアプリケーション自体は、Cocoa アプリ(つまり、Objective-C)として動いているんだ。下の 'Say Hello To The World' ボタンを押すと、アラートパネルが表示されて、Say Hello と書かれているんだ。で、まん中にあるラヂオボタンがみそだ。一番上を選ぶと、普通に、Objective-C から Objective-C を呼び出す。二番目は、Objective-C から C++ のコードを呼び出して使っている。最後は、Carbon のコードを呼び出す、ということらしい。 さて、ソースコードの中身をのぞいてみよう。肝となるのは SayHello.m っていうファイルだ。ここに、message1、message2、message3 っていうメソッドがあって、それぞれラヂオボタンに対応している。 message1 では、単に、NSRunAlertPanel を呼び出しているだけだ。これが一番簡単なやつね:
一つ飛ばして、message3 では、Carbon のコードを呼び出している。これも、直接呼んでいるだけだ。ここでは Carbon のコードは C で書かれているので、Objective-C から問題なく呼び出せる。Objective-C は、C のスーパーセットなので(この位置付けは C++ と同じだ)、C のコードは透過的に呼び出せる。さらに、この場合は、Carbon のコードも問題なくいきなり呼び出せるらしい(他のものはどうなのか?):
で、message2 の話。message2 では、最終的には NSRunAllertPanel を呼び出すんだけど、その前に、必要な情報を C++ のコードから取得するような作りになっている。Foo というクラスで、FooClass.h に定義がある。だけど、Objective-C から直接 C++ のコードは呼べない。どうするかというと、WrapperForCpluPlus.h っていうファイルの中にあるように、C で C++ をラップする関数を作って、それを経由して C++ のコードを呼び出すんだ。 Objective-C -> C wrapper -> C++
fooGetVariable()、fooStoreObjCObject()、deleteFoo() っていうのが、ラップしてる C 関数だ。 それだけ?うん、それだけのことのようだ、、、 January 22, 2001■フェード・イン、フェード・アウトアニメーション (1):NSTimer を使うきのう、半透明表示をしたので、それを使って、フェード・イン、フェード・アニメーションをしてみよう。アイコンが、消えた状態からだんだん現れてきて、まただんだん消えていく、ってやつね。 アニメーションのためには、周期的に View の drawRect を呼び出してやる必要がある。いくつか方法が考えられるんだけど、今回は NSTimer を使ってみよう! NSTimer を使うと、一定時間後に、指定したメソッドを呼び出すことができる。さらに、周期的に呼び出すこともできる。クラスメソッド scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: を使うんだ。名前なげーな、おい。
と、パラメータを指定すると、時間間隔 0.05 秒で、self の firedByTimer っていうメソッドを、引き数 nil で、繰り返し呼び出す、ってことになる。もぅ、プログラムをそのまま自然言語に直せるね。 ここから分かるように、Objective-C では、コールバックを target(クラスのインスタンス)と、selector(メソッド)の組みでいきなり呼び出せるわけだ。メソッド呼び出しを、メッセージパッシングで処理する Objective-C ならではだね。static 関数にしないと、クラスのメンバ関数をコールバックにできない C++ や、interface を作って、implements してやる手法の Java とかと比べて、はるかにお手軽に使えるよ。これって、結構有利だと思う。 アニメーションの続きは後日。 January 22, 2001■NSOutlineViewDataSource の implementation先日の続きの NSOutlineView の DataSource ね。 NSOutlineViewDataSource のドキュメントによると、こいつには 7 つのメソッドがある。そのうちの 4 つが必須だ。残りの 3 つはオプションね。ちなみに、必須メソッドを外してもコンパイルは通る。だけど、実行時にエラーになる。Java の abstract みたいに、コンパイラ時にエラーになってくれればいいのにー。と、思ったけど、Objective-C の場合は、実行時にリンクが解決されるから、コンパイル時にエラーを吐くわけにいかないんだ。うーん、なるほど。どっちがいいのかな? 例として、次のような木構造を考えてみよう。
root として、A がいて、その子供に B、C、D がいる、っていう構造だ。この木をどうやって DataSource にしてやるのか?必須のメソッドだけ見てみよう。 - numberOfChildrenOfItem
これは、あるノードに子供が何人いるか?っていうメソッドだね。item として、A が来た場合には 3、B - D が来た場合には 0、って返せばいいわけだ。気をつけるのは item が nil のときは、root の数を聞いてきているんだ。この場合は 1 を返せばいい。1 以外を返すことも可能だから、この View は複数 root をサポートしているんだね。 - isItemExpandable
指定した item は開くこと、つまり三角ボタンをクリックして子供を表示することが可能か?って聞いてきたわけだ。item が A なら YES、それ以外なら NO だね。 - childOfItem
item の index 番目の子供を返してくれ、っていうメソッド。item が nil の場合は root item を聞いてきてる。したがって、item == nil で index == 0 のときは(この場合 index は 0 しか聞いてこないはず)、A を返す。item == A のときは、index に合わせて、B、C、D を返す。 - objectValueForTableColumnByItem
さて、いちばんの肝となるメソッドだ。指定された tableColumn に、item を表示するためのオブジェクトを返せ、っていうことだ。上の例で、仮に、View に文字列で 'A' とか 'B' とか表示するとしよう。そのときは、NSOutlineView がデフォルトの状態だとすると、NSString へのポインタを返せばいい。@"A" とかやればいいんだ。 最後のメソッドはちょっと面倒なので、もう少し詳しく見るとしよう。 January 21, 2001■画像の半透明表示Mac OS X を、他のたくさんの GUI システムに対して、比類なきものにしているものは?それはもちろん、半透明でしょ、おにーさん。Aqua がなかったら、Windows と区別つかないもんなぁ、普通の人にしてみれば。 というわけで、Mac OS X の命綱、画像の半透明表示をやってみよう。今回は NSImage を使う。NSImage には、半透明で表示するための dissolveToPoint というメソッドがあるんだ。これを使えば一発!さっそくやってみよう。まず、Interface Builder で、NSImage の Subclass を作る。仮に名前を、DissolveIconView としとこう。そして、ウインドゥに適当に Custom View を張り付けて、class を DissolveIconView に指定する。DissolveIconView を Create Files したら、Project Builder に戻って来よう。 さて、ソースだ:
まず interface の方。NSImage へのポインタを一個用意した。次は implementation の方:
メソッドを二つ用意した。awakeFromNib と drawRect だ。 awakeFromNib は、アプリケーションが立ち上がって、リソースが用意されたところで呼び出される。ここで、画像を用意する。とりあえず、また、シャーロックのアイコンを使うよ。 で、drawRect。このメソッドは、View が画面に描かれるとき呼び出される。ここで、dissolveToPoint を呼んでいるんだ:
このメソッドを呼ぶときは、画像を表示する場所を point として指定し、半透明の度合いを fract で指定するんだ。fract の値は 0.0 から 1.0 の間ね。こうして表示させたのがこんな感じ:
左から順に、0.0、0.2、0.4、0.6、0.8 ね。半透明表示ができたよ。これでより Mac OS X ライクになるね(何が?)。 January 21, 2001■NSOutlineViewDataSource についてNSOutlineView っていうクラスがあるよね。階層構造を表示するための View だ。その View がなにを表示するか決めるのが NSOutlineViewDataSource プロトコルなんだ。詳しくいうと、NSObject に適用される informal protocol だ。この informal protocol と、カテゴリっていうのは同じものと考えていいいの?誰か教えて。 NSOutlineView は、NSTableView から継承されたクラスで、NSTableView のヘッダファイルの方に、NSOutlineViewDataSource へのポインタが定義されている:
id 型だね。で、この dataSource は、Interface Builder から設定できるんだ:
したがって、dataSource を伴った NSOutlineView の使い方は次のようなステップをふむ:
これで、NSOutlineView に、データを表示させる準備ができた。その実装の中身は、、、また後で。 January 20, 2001■Class の名前を表示するある id 型の変数があったとしよう。さて、こいつのクラスはいったい何だ?早速調べてみよう! まず、Class 型を表示する。id に代入されているものが、NSObject から派生されているものならば(たいていはそうだ)、class メソッドを使うことができる。class メソッドは、NSObject の protocol として、定義されている:
Class 型が得られたら、次はどうするか?こいつの名前を知りたいよね。そのためには、NSStringFromClass() という、そのものずばりの関数がある。解説は、FoundationKit の Functions のページに書いてある:
最後の行の、cString というメソッドは、NSString のメソッドで、C 言語型の文字列を得るメソッドだ。これで、クラスの名前を知ることができるぜ! January 20, 2001■NSApp って何?ProjectBuilder を使って、Cocoa アプリケーションを作ると、main.m っていうファイルができて、次のようなコードが書かれるよね:
この NSApplicationMain() って何?NSApplication のドキュメントによれば、この関数は次のような関数と同値らしい(これそのものでは、ないらしい):
まず、Cocoa のアプリケーションは、かならず NSApplication のインスタンスを一個作らなくてはいけない。それを作るのが、sharedApplication メソッドだ。で、このメソッドを呼ぶと、インスタンスが作られるんだけど、そのポインタは次のようなグローバル変数に入れられる:
この変数、NSApp は、AppKit/NSApplication.h に宣言があるよ。でも extern だから、本体はどっか別にあるんだな。この値は、NSApplication.h を import しておけばどこからでも参照できるから、自分のアプリケーションにアクセスしたいときは、いきなり NSApp を使えばいいんだな。 January 19, 2001■僕は iTunes に嫉妬するiTunes をダウンロードした。この文章はインターネット・ラジオを聞きながら書いている。 ユーザインタフェースがガイドラインから外れていることは、さて置こう。今は、Mac OS X への移行のための、ガイドラインの過渡期だと思える。Apple も試行錯誤しているのだと思う。 しかし、実にシンプルで使い易いインタフェースではないか。使い易さを優先したため、機能が制限されているきらいはある。しかし、それは機能過多による、複雑で醜悪なインタフェースをさけるためのトレードオフではないか?ほとんどの機能をメニューを介さずに、ドラッグ・アンド・ドロップで操作できる。この直接さこそが、Mac の持ち味ではないか。 しかし、僕は iTunes の一番の特徴は、Visual にあるのではないかと思う。Visual を選択すると、プレイリストは消え、漆黒のスクリーンが表示される。始めに、白の Apple マークが浮かぶが、それは周りから現れる、映像の波の中に飲み込まれ、静かに消えていく。映像は強烈であるが主張はなく、パターンはあるが同じものとは認識されにくい。美しく、かつ暴力的なまでに変遷を繰り返す映像を眺めていると、自己の意識が溶け出していくのを感じる。 また、映像の動きには、断絶がない。二つの映像のつなぎは、フェードイン、フェードアウトで処理される。それにより、主である音楽の流れを断ち切ることなく存在することに成功している。その手法は、フルスクリーン化する際にも用いられ、細やかな心遣いが感じられる。 僕は iTunes に、プログラマとして、嫉妬する。その確かな技術力に、アプリケーションをまとめる調和性に嫉妬する。そこには、ソフトウェアをひとつの「モノ」として昇華させようという、意志が感じられる。この美意識がある限り、Apple は大丈夫だ。 January 17, 2001■NSOutlieView の構造ちょっと話を前に戻して、NSOutlieView の話です。NSOutlineView は、Finder のリスト表示みたいな、木構造を実現する View のことだ。その実現のために、複数の View が組み合わされている。目に着くものを軽く書いてみると、以下のようになってるんだな:
リストのヘッダを表示する Header View、スクロールバーの上にある Corner View、リストの内容を表す Table Columns、スクロールさせる Scroll View。ざっと見ても、これだけの View があるんだ。 じゃ、実際のコードではどうなっているんだろう?まず、第一に、NSOutlineView は NSTableView を継承してるクラスだ。上に挙げた構成要素は、NSTableView のメンバなんだな。そのことを頭において、NSOutlineView の構造を図にしてみた:
まず、NSOutlineView は NSTableView の子クラス。そして、NSTableView はいくつかのメンバを持っている。ヘッダを表す _headerView は NSTableHeaderView 型。コーナーを描画する _cornerView は NSView 型。そして、テーブルの中のアイテムは NSMutableArray に入っていて、その中身は NSTableColumn 型だ。 NSTableColumn は、ヘッダを描画するための _headerCell と、アイテムを描画するための _dataCell を持っている。それぞれは、保持されている型は NSCell 型だけど、デフォルトでは、それぞれ、NSTableHeaderCell、NSTextFieldCell が入ってるんだ。 てなわけで、これでざっと NSOutlineView のことが分かったかな、、、 January 15, 2001■アプリケーションを起動する:NSWorkspace を使ってアイコンが表示されたら、とうぜん(か?)アプリケーションを起動させたくなるよな。NSWroksapce を使うと、極めて簡単。launchApplication を使えば、一発で起動できる:
このメソッドは BOOL を返すんだ。起動が成功するか、すでに起動していれば、YES、失敗すれば NO が返る。引き数にはアプリを指定する。フルパスでなくてもよろし。".app" をつけてもつけなくてもよろし。 ま、これだけだとつまらないので、きのうのアプリをいぢって、アイコンをダブルクリックすると起動するようにしてみた。きのうのコードに以下のものを付け加えるんだ:
mouseUp は NSResponder からオーバーライドしたメソッド。引き数として渡される NSEvent の clickCount からクリック数を知ることができるんだ。ここでは 2 回クリックされたときに、アプリケーションを立ち上げてる。決め打ちだけどね。 ここまでくれば、ラウンチャが作れるなぁー。 January 14, 2001■NSWorkspace を使ってアイコンを表示するやはり Mac のリソースといったら、アイコンだろう!というわけで、アイコンを表示させてみよう。アイコンは .app の中の .icns というファイルにしまわれている。このファイルのパスは Info.plist からたどれるわけだ。しかぁーし、この .icns ファイルのフォーマットが分からない。ドキュメントは公開されていないのか?しかぁーし(しつこい)、簡単に .icns ファイルから画像を読み出す方法がある。それが NSWorkspace を使う方法だ。このクラスの iconForFile メソッドを使うと、NSImage 型でアイコンの画像を読みだせるんだ。 今回は InterfaceBuilder を使った。IB で ImageView のサブクラス、IconImageView を作る。そして、ウインドゥに適当に CustomView を張り付けて、クラスに IconImageView を指定するんだ。そして、Create Files を呼び出す。 IconImageView では、とりあえず initWithFrame をオーバーライドした。以下ソースコードだ:
肝は NSWorkspace に関するところだ。NSWorkspace はアプリケーションごとに一個インスタンスが作れらるらしい。それをクラスメソッド sharedWorkspace で取り出すことができる:
そのインスタンスから iconForFile を呼び出す。このメソッドは、パスを指定すると、そのファイルのアイコンの画像を取ってきてくれる、すげー便利なものなんだ:
画像が得られたら self に setImage してやると。これでアイコンが表示できたぜ! January 14, 2001■Info.plist にアクセスする from Core Foundationきのうは NSBundle から Info.plist を読みにいったけど、きょうは Core Foundation からいってみよう!メインは Core Foundation の Bundle Service を使うことだ。NSBundle とほとんど同じなんだけどね。まずはソースコードだ:
NSBundle 用のコードを読んだ人ならばすぐ分かるでしょう。まず、システムパスを CFURLRef の形でつくる:
そして、それを使って CFBundleRef をつくる:
その bundle から、Info.plist の内容が含まれる CFDictionary を GetInfoDictionary を使って取ってくる:
これで OK だ!ためしにアクセスしてみよう。CFBundleIconFile の値を取ってみよう。次みたいなコードを挿入してみて:
"Edit.icns" と表示されるはずだ。先日、NSBundle からアクセスすると、すべての key が NSString になってしまうようだ、と書いたけど、Core Foundation を使うと大丈夫みたいだ。あんまり厳密にテストしてないけど。 ところで、CFDictionary って、含まれているすべてのオブジェクトに簡単にアクセスする方法がないような気がする。つまり、Enumerator 系の関数が用意されていないような気がするんだ。ということは、key の値が分かっていないとアクセスできないのか?それとも何か方法があるのかな? January 13, 2001■glclock を動かしてみたglclock を動かしてみたよ。glclock は Masa(川瀬 正樹)さんの作った OpenGL による 3 次元懐中時計プログラム。時計として使うよりは、OpenGL の機能のデモのようなものだそうだ。プログラムは GLUT をベースにしているので、ほぼ問題なくコンパイルが通ったよ。動作速度も良好。ただし、ウインドゥをいぢくっていると、時々挙動がおかしくなった。MacOS X Public Beta の GLUT にはまだ少し問題があるようだ。でも、ざっと動かしたところは結構いい感じ。
January 13, 2001■Info.plist にアクセスする from NSBundleさて、Info.plist の中身をプログラムから読んでみようか。まずは、NSBundle を使ってみる。さっそくソースコード。以下の通りだ:
このプログラムでは、アクセスするアプリケーションをフルパスで指定している。ま、手抜きだね。とりあえず、TextEdit を指定している:
そして、NSBundle のファクトリメソッド bundleWithPath を使って、NSBundle のインスタンスを作る:
インスタンスから、infoDictionary を使うと、NSBundle から Info.plist を NSDictionary 型で取得することができるんだ:
で、その後、Info.plist の中身を NSEnumerator を使って触ってみたんだけど、どうも、すべての key が NSString になっているらしいんだ。Info.plist の中には NSDictionary 型や NSArray 型の key もあるはずなんだけど、NSString になっているようだ。これが仕様なのか、未実装なのか、使い方が間違っているのか、よく分かんなーい。 January 12, 2001■Info.plist の中身 for NSBundleInfo.plist の中には、接頭子 CF で始まるものの他に、NS で始まるものもある。こいつらはいったいどこで定義されているんだ?Cocoa のドキュメントを探してみると、Resource Management の章があやしいんだけど、Description forthcoming になっている。つまり、まだ書かれていないわけだ。うーん、残念。 仕方ないので、API Document の NSBundle の項を読んでいたら、infoDictionary のところに、少しだけ記述があった。それによると、Info.plist の共通の key は、NSExecutable、NSExtensions、NSIcon、NSMainNibFile、NSPrincipalClass だそうだ。 NSMainNibFile や NSPrincipalClass は、いかにも Cocoa 環境でしか使わなさそうだね。それに対して、NSIcon とかは CoreFoundation で定義しているものとかぶりそうだ。この辺の使い分けはどうなるんだろう?と、いぶかんでもドキュメントが出てくるまでは分からないよなあ。 January 7, 2001■Info.plist の中身きょうは時間がないから、手短にいくよぅっ! きのうは ProertyListEditor で Info.plist をのぞいたけど、この XML ファイルの定義はどうなっているんだ?それは、CoreFoundation のドキュメントの中に書いてあるんだ。/Developer/Documentation/CoreFoundation からたどれるよ。 まず、使われている XML タグの種類は?Property List XML Tags に記述がある。こんな感じだ:
そして、key として使われている要素の定義は?これは Bundle Services の More About the Info.plist File の中に定義がある。Standard Keys と Finder の Keys が紹介されているんだ。詳しい中身はまた後日。じゃ! January 6, 2001■PropertyListEditor を使うNSBundle の話の前に PropertyListEditor を使ってみよう。PropertyListEditor は、Developer Tool をインストールするときいっしょに入れられる。/Developer/Applications にあるよ。
まず、アプリケーションファイルの中身を見てみよう。アプリケーションアイコンの中は実はディレクトリだってのは知ってるよね!?一番簡単に中身を見るには、Finder でアプリケーション・アイコンを選択した状態で、control + クリックするんだ。そしてコンテクスト・メニューから "Show Package Contents" を選択するんだ(日本語版では何ていうんだ?)。そうすると、別のウインドゥで中身が見れるよ。 さて、中を見ると、ルートが Contents って名前になっていて、その中にいくつかのファイルがあるだろう。今回注目するのは、"Info.plist" ってファイルだ。これをダブルクリックすると ProertyListEditor が立ち上がって、中身が見れるぞ。こんな感じだ:
色んなプロパティとその値が登録されていることが分かるよね。これらの取得の仕方と内容は、また次回だ。CoreFoundation の方にも手を伸ばさないとなぁ。ちなみに、アイコンに XML と書いてあるところからわかるように、"Info.plist" の中身は XML だ。普通のテキストエディタや、他の XML エディタでものぞけるよ。 January 3, 2001■Cocoa プログラミング Tips: OutlineView Example での NSFileManager の使い方ちぁっす! 前振りなしで、いきなりきのうの続きだ。Developer Tool についてくる Example、OutlineView を見ていたけど、きょうはファイルの探りかただ。 ファイルを取り扱っているのは、Example の中の、クラス FileSystemItem だ。このクラスは OutlineView で表示するために、帰納的にアクセスするように作られている。parent があって、children がいて、parent が nil だったらルートだー、っていうアレね。<こんな説明でいいのかよ。 さて、実際にファイルシステムにアクセスしているのは、メソッド children だ。ここでは NSFileManager を使っているんだ!NSFileManager の使い方はけっこう簡単。まず、ファクトリメソッド defaultManager で、インスタンスを取得する:
そのインスタンに対して必要なメソッドを呼び出してやる。Example で使っているのは、fileExistAtPath:isDirectory と directoryContensAtPath の二つだ:
この関数の機能は、読めば分かるよね。前者は path で指定したファイルが存在するかどうか、かつそれがディレクトリかどうかを調べる。後者はディレクトリの中身を取得する。 一つ注意するのは、前からよく言われていることだけど、Classic な MacOS のようにファイル ID でファイルにアクセスするのではなく、完全にパスベースになっていることだ。これに関しては賛否両論、喧々諤々あるよな。ここでは、とりあえず、パスベースの方が新規に参入する人には楽なんじゃない、という立場を取っておこう。 NSFileManager を使うと、ファイルの生成、削除、ディレクトリの調査、シンボリックリンクの作成なんかができるみたいだ。じゃあ、ファイルに格納されているリソースを取り出したいときは?ふっふっふ、それは NSBundle を使うんだよ。というわけで、後日に続く。 January 2, 2001■Cocoa プログラミング Tips: Example に見る NSOutlineView の使い方正月休みなのをいいことに、久しぶりに MacOS X の開発環境をいじりまくってるよ。 そこで、脈絡がないけど、Developer Tool の Example である OutlineView をいぢくってみたので、解説してみよう。OutlineView は、ひとことでいえば、Finder のリスト表示を実現するアプリケーションだ:
じゃあ、ざざっと解説するぞ!きょうは、どうやってリスト階層を表示しているか?という点に着目してみよう。まず、このプロジェクトには .nib ファイルが一つある。MainMenu.nib だ。これを Interface Builder で開けてみよう。重要なコンポーネントは二つある。まず一つ目は MyWindow ね。この Window は中に NSScrollView を一つ持っている。ScrollView っていうのは、リスト表示をするやつのことだ:
もうひとつ、大事なものは、DataSource というクラスがある。これは NSObject のサブクラスだ。ただし、Outlet も Action もなんもなし。インスタンス化はされているんだ。 この二つが、この .nib ファイルの重要なアイテムなんだ。NSScrollView と、DataSource ね。さて、ここからが肝なんだけど、Inspector を表示させて、Window の中の NSScrollView のデータを表示するところをダブルクリックしてみよう。NSScrollView は、内部に NSOutlinewView を持っているんだ。ダブルクリックすることによって、NSOutlineView のインスペクタを表示させることが出来る:
これを見ると、dataSource と delegate っていう二つの Outlet が DataSource に接続されていることが分かるよね。こうすることによって、NSOutlineView に表示させる内容と、DataSource クラスを結び付けているんだな。うーん、IB だねぇ。 じゃあ、次は DataSource クラスのソースコード見てみよう。ヘッダファイル DataSource.h では、NSObject から継承しているという情報だけで、なんのメソッドも宣言されていない。実装部である、DataSource.m の方では、五つのメソッドが定義されている。その内の最初の四つは dataSource に関するもので、残りの一つは delegate に関するものだ:
さて、これらのメソッドは何から継承されているのか?AppKit のリファレンスで、NSOutlineViw を見てみよう。すると、NSOutlineViewDataSource という informal protocol があることが分かるんだ。Data Source クラスでは、この protocol を実装しているんだな。さらに、NSOutlineViewDelegate という protcol の存在も分かる。でも、これに関してはドキュメントが見つからなかったよ。そこで、ヘッダファイル AppKit/NSOutlineView.h を見ることによって、定義を知ることができるんだ。これらの protocol のうち、必要なものを実装するだけで、outline view をコントロールすることができるんだな。 ちょっと DataSource クラスの実装を見てみよう。このクラスの実装では、FileSystemItem というクラスをサポートとして使っている。実際にファイル名を調べるのはこっちのクラスなんだな。NSFileManager を用いることによって調べているようだ。 ちなみに、よくわかんないけど、このアプリケーションのアイコンはねこになっている。謎だけど、mkino はねこ好きだからよしとしよう(笑):
January 1, 2001■Cocoa プログラミング Tips: コマンドラインから Cocoa を呼び出すときの注意点あけましておめでとうございます。しかーし、新年のあいさつも、21 世紀のはじまりも特に気にせずいつもどおりに行くぞっ。 きょうは Cocoa プログラミングの初歩的な Tips だ。Classic な MacOS プログラミングと比べて、MacOS X のプログラミングのさいに、やっぱり便利なものはなにか?それは、標準のコマンドラインの存在だと思うんだ。もちろん、アプリケーションとして仕上げるときは使わないけど、デバッグの段階では便利だよね。 でも、いざコマンドラインを使ってみると、問題があることに気付くと思うんだ。C や C++ の標準ライブラリ(stdio とか)だけのときは特に問題ない。でも、AppKit や Foundation Kit のクラスを使おうとすると、"_NSAutoreleaseNoPool()" っていうエラーコメントが表示されないかい? AppKit では(というか Objective-C 自体にそういう傾向があるのか?)、メモリ管理に、参照カウンタを用いた、自動的なオブジェクトの削除を行っているらしい。もうちょっと厳密に言うと、AppKit のルート・オブジェクトである NSObject が、参照カウンタ機構の存在を前提に設計されているんだ。その管理を行うのが NSAutoreleasePool だ。 Project Builder でテンプレートを使ってアプリを作る場合は、自動的に NSAutoreleasePool が作られるから、気にしなくてよろしい。でも、コマンドラインのアプリを作るときは、自分で作らなくちゃいけないんだ。そのようなときは、次のおまじないを呼ぶ:
まず、NSAutoreleasePool のインスタンスを作る。そのあとで、AppKit や FoundationKit の関数を呼び出す。最後に NSAutoreleasePool の release を呼び出して、オブジェクトを削除する。これで、とりあえず OK だ。 細かいことは Foundation-Kit douments の NSAutoreleasePool の項を読んでくれ。もっと突っ込んだ解析は後日やるかもしれない。じゃ! |
|
Home | Link | Download | Back Number | Speciall Issue
|