![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ||
![]() | ![]() | ![]() | ![]() | ![]() |
|
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
以下は、Mac OS X 10.4.11 上の Xcode 2.5 で説明しています。
SimpleBrowser は、Cocoa の NSBrowser クラスの使い方を示す小さなアプリケーションです。このアプリケーションは、表示メカニズムとして NSBrowser を使った、ファイルシステムブラウザを実装します。ブラウザは、ファイルシステムを移動させ、書類やアプリケーションを起動させたり開きます。このサンプルコードは、以下のことを実演します。
NSBrowserCell の使用NSBrowser 機能主なソースファイルと、それらについて何が興味深いかを以下に説明します。
AppController オブジェクトは fsBrowser オブジェクトの委任です。ブラウザの委任は、browser:willDisplayCell:atRow:column: と、browser:numberOfRowsInColumn: または browser:createRowsForColumn:inMatrix: のどちらかのメソッドを実装しなければなりません。この AppController は、browser:numberOfRowsInColumn: を実装し、したがって fsBrowser はそのデータを遅延読み込み (lazily load) します。ブラウザセル内のセルの読み込みにはディスクを操作することが含まれているので、ブラウザが遅延であるのは適切であるように思われます。
AppController は、ブラウザのシングル/ダブルクリックアクションを、それぞれ browserSingleClick: と browserDoubleClick: に設定します。シングルクリックを受けとったとき、ブラウザは現在の選択範囲についての情報を表示します。ファイルに対するダブルクリックはそのファイルを開き、一方、アプリケーションに対するダブルクリックはプログラムの起動をもたらします。
FSNodeInfo オブジェクトによって与えられたアイコンとファイル名の両方を表示する NSBrowserCell のサブクラスです。
単一のファイルシステムノードについての情報、それがファイルまたはディレクトリのどちらかを維持管理します。特に、FSNodeInfo は、ファイルの絶対パス、最後のパス成分、読み込みアクセス権 (read accessiblity) などを返すことができます。
アプリケーションを起動すると次のようになります。
![]() |
図では、Xcode.app を選択した状態を示しています。Finder と似ていますが、ファイルシステムから情報を得ているため、パッケージの中身が丸見えになっています。標準のブラウザ機能を備えていることを確認してみてください。ダブルクリックすると Xcode が起動します。矢印キーで上下左右に動けます。シフトを押せば複数選択できます。ドラッグができないことに注意してください。
メニューには「Debugging(デバッグ)」という項目があり、その「Reload Browser Data(ブラウザのデータを再読み込み)」を選択すると、ブラウザのデータが再読み込みされます。このとき、ブラウザの選択範囲が最初の状態に戻ります。
Xcode でプロジェクトを開くと、以下のようになっています。
![]() |
Classes に、AppController.h と .m があります。このクラスは MainMenu.nib 内でインスタンス化されていて、NSBrowser インスタンスの委任にされています。アプリケーションの委任にはされていません。このクラスがアプリケーションの主要な動作を行います。
FSBrowserCell.h と .m は、NSBrowserCell のサブクラスを定義します。ブラウザのセルの独自の表示を担当します。
FSNodeInfo.h と .m は、は、ブラウザ内の項目情報を扱う NSObject のサブクラスを定義しています。
Resources 内には、Images というサブグループがあり、そのなかには画像が入れられています。MainMenu.nib は、このプロジェクトの主要 nib ファイルです。
MainMenu.nib を開くと、以下のようになっています。
![]() |
AppController クラスがインスタンス化されています。これを選択してアウトレットを表示させると、fsBrowser がウインドウ内のブラウザに、nodeIconWell が右上の画像ビューに、nodeInspector が右下のテキストフィールドにそれぞれ接続されています。
逆にブラウザを選択してみると、delegate(委任)が AppController に接続されています。ウインドウ内のどの項目もアクションはありません。ウインドウの initalFirstResponder がブラウザになっていることに気をつけてください。
メニュー内の項目は基本的に一次レスポンダに接続されていますが、1 つだけ「Debugging(デバッグ)」>「Reload Browser Data(ブラウザのデータを再読み込み)」は、AppController インスタンスの reloadData: に接続されています。
AppController クラスAppController.h のインターフェイス宣言は以下のようになっています。
インタンス変数は MainMenu.nib 内で接続されていたアウトレットだけです。メソッドのうち上のものは、メニュー項目に接続されていました。下の 2 つのメソッドは、次の初期化の説明で出てきます。
さて、AppController クラスは、MainMenu.nib でインスタンス化されているので、アプリケーションが起動し、nib ファイルが読み込まれた時にインスタンスが作られることになります。このとき、awakeFromNib が送られます。AppController ではこのメソッドを使って必要な初期化作業を行っています。このメソッドは以下のように実装されています。
まず、ブラウザが独自のセルクラスを使うように設定しています。このクラスについては、後で説明します。
次に、クリックされた時のアクションを設定します。nib ファイルでブラウザにはターゲットもアクションも設定されていませんでした。これらはブラウザがシングルクリックされた時に送られるアクションメッセージです。さらにダブルクリック時のアクションも設定しています。
次に表示される最大列数を設定しています。MAX_VISIBLE_COLUMNS は、実装ファイルの最初で定義されている定数です。これはあくまで最大列数です。サンプルを起動すると最初に表示されているのが 3 列であることに注意してください。サイズ変更コントロールを引っぱって横に広げると、ブラウザが 4 列になります。それ以降は、どれほど引っぱっても 4 列のままです。さらに列の最小幅を設定しています。
最後に、ブラウザにデータの再読み込みをさせています。このクラスの reloadData: を呼び出しています。このメソッドは、以下のように実装されています。
このメソッドは、メニュー項目からも呼び出せるようにアクションメソッドの形になっています。NSBrowser のインスタンスメソッドを呼び出しているだけです。これは以前に読み込まれたデータを読み込み解除(作られたリソースなどを解放)して、新たにデータを読み込みます。
さて、これでアプリケーションの初期化作業は終了し、あとはユーザーの操作を待っている状態になります。Cocoa に慣れていない方は、不思議に思ったかもしれません。起動した状態で、ウインドウ内のブラウザには、ディスク内容を示すデータが表示されています。このデータはどこで設定されていたのでしょう。
Application Kit 内でデータを表示するクラスのうち、多量のデータを表示するテーブルビューやアウトラインビュー、そしてブラウザなどのクラスは、データを明示的に設定しません。そのかわり、必要な時にデータを提供する別オブジェクトを用意するようになっています。テーブルビューでは、これはデータソースと呼ばれ、NSTableDataSource 簡易ブロトコルを実装しているオブジェクトが設定されます。ブラウザの場合、これは委任が担当します。
ブラウザの委任は、データを提供し、枝 (branch)(下にさらに項目がある)または葉 (leaf) (終端)ノード、有効または無効として各項目を設定します。スクロールのようなイベントを受けとったり、編集可能な場合の変更の検証も行えます。ブウラザの委任は、browser:willDisplayCell:atRow:column: と、browser:numberOfRowsInColumn: または browser:createRowsForColumn:inMatrix: のどちらかを実装しなければなりません。つまり、最低でも 2 つのメソッドは必ず実装していなければならないわけです。後の 2 つは両方実装できません。
browser:willDisplayCell:atRow:column: は、特定の行と列を表示される前に呼ばれます。このメソッド内でセルの文列値データを設定したり、それが枝か葉かなどを設定します。必須メソッドの後の 2 つのうち、browser:numberOfRowsInColumn: は特定の列内の行の数を返すものです。これを実装したブラウザの委任は受動的と呼ばれ、データ自体は、先の browser:willDisplayCell:atRow:column: で設定することになります。browser:createRowsForColumn:inMatrix: の方を実装したブラウザの委任は能動的と呼ばれます。このメソッドでは、列を表示するためのマトリックスが与えられるので、その列のなかに表示されるセルを配置します。その結果のマトリックスをブラウザがそのまま表示します。これによって、細かい表示の調整を行えるので、能動的と言われます。逆に受動的な委任は表示の詳細はブラウザクラスにまかせることになります。能動的な委任の場合、表示をすべて作ってしまうので、べつに browser:willDisplayCell:atRow:column: 内で何かを行う必要はありません。ただし、たとえ何もしなくても、このメソッドは実装しないと例外が発生してしまいます。
AppController は、browser:numberOfRowsInColumn: を実装しているので、受動的ということになります。よって列内の表示は基本的にブウラザにまかせることになります。実際、Finder 風の通常のリスト表示になっています。ただし、独自のセルを使っているため、セル内にアイコンが表示されるなど、単なる文字列ではありません。通常のセルを使っていれば、単に文字列値を表示したりという風になります。能動的なセルでは列内のマトリックス自体を修正可能なので、もっと違う形の表示も可能になるわけです。
さて、データの読み込みがどのように行われているかがわかったので、ここで委任メソッドを調べればいいのですが、このサンプルではファイル階層のデータを表示するようになっていて、そのためのノードクラスを定義しています。これを理解してからでないと、委任メソッドを見ても何のことがわからないので、まずこのデータを表すクラスを調べてみます。
FSNodeInfo クラスこのサンプルにおけるデータは、ファイルシステム上の項目です。ひとつひとつの項目は、FNNodeInfo クラスで表されています。まずこのクラスのデータ構造を見てみましょう。FSNodeInfo.h の一部を以下に示します。
このクラスは 2 つのインスタンス変数を持っています。parentNode は親のノードで、このクラスのオブジェクトです。これにより、下から上へと参照の連鎖があることになります。相方向リストではなく、子の集まりがないことに注意してください。relativePath は相対パスですが、すぐ上の親からなのでたいていは名前だけになるでしょう。
このクラスはデータ構造でいう木構造を表しています。知らない方はデータ構造を説明している本またはサイトを見てください。Cocoa では直接の木構造コレクションはありませんが、AppKit サンプルの DragNDropOutlineView に単純な木構造クラスがあります。この実装はちょっと難があるのでそのまま使い続けるのはすすめられませんが…。あとは、Core Foundation に CFTree があるので、これが使えます。DragNDropOutlineView の実装では、インスタンス変数として子の配列を保持しています。このサンプルでは、それがありませんが、これはファイルシステムを調べれば、子がわかるので、その部分が省かれています。
作成メソッドは、自動解放オブジェクトを返すクラスメソッドと、初期化メソッドの 2 つが宣言されています。クラスメソッドのほうは、以下のように実装されています。
見てわかるとおり、初期化メソッドが呼ばれて、返されたオブジェクトを自動解放して返しているだけです。実質的には、initWithParent: atRelativePath: がすべての初期化を担当していることになります。このメソッドは、以下のようになっています。
単に引数をインスタンス変数に設定しているだけです。parentNode は保持されず、relativePath は保持されていることに注意してください。したがって、dealloc が保持したものを解放するために定義されています。
これで、このクラスがどういうデータを持っているかがわかったと思います。これだけでは意味がありません。このクラスは、他に、子ノードの配列を返すメソッドや、現在のインスタンスが表しているファイルシステム上の項目に対する情報を取得するメソッドを宣言し、定義しています。
まず子ノードの配列を返すメソッドを見てみます。
まず [NSFileManager defaultManager] で、共有ファイルマネージャーを取得しています。これはアプリケーションで用意されていて、いつでも取得できます。このメソッドは、まだ作成されていなければそれを作り、すでに作っていれば、それをそのまま返すので、プログラマが心配することはありません。そして、directoryContentsAtPath: により、引数パスにあるディレクトリの内容を取得しています。このクラスが所持しているのは相対パスなので、[self absolutePath] でまず自身の絶対パスを作っていることに注意してください。これは NSArray を返します。そこで、objectEnumerator を呼び出しています。このオブジェクトは、項目をひとつずつ取り出して繰り返しを行うときに使います。 そして項目ひとつずつ、自分を親にしてノードを作成し、それを配列に入れていきます。最後までくれば [subNodePaths nextObject] が nil を返すので、subNodePath に nil が代入され、while 文が終わります。
このクラスには、visibleSubNodes というメソッドもあります。これは、上と同様ですが、項目のノードを作成するときに、隠しファイルかどうかを調べて、隠しファイルは含めない点が違います。
このクラスは、情報取得のためのメソッドも宣言しています。fsType は、ディレクトリかどうかを示す文字列を返します。
ここで使われている isDirectory は次のようになっています。
共有ファイルマネージャーを取得し、absolutePath で絶対パスを取得して、ファイルマネージャーにそこにあるファイルがディレクトリかどうかを問い合わせています。BOOL 値 exists はファイルが存在しなければ NO が返るので、最初にこれとディレクトリかどうかを && 演算しています。よってこのメソッドは、ディレクトリであれば YES、ディレクトリでないか、または存在しなければ NO が返ることになります。
直前のメソッドや、子ノードの所でも、absolutePath が使われていました。このクラスは、インスタンス変数として相対パスだけを保持しているので、直接絶対パスが使えません。絶対パスはそのつど計算することになります。
親ノードがなければ、自分の保持しているパスをそのまま返し、親があればその absolutePath を呼び出して、戻ってきた値をチェックして、「/」なら「」にしてます。そして親の絶対パスと自分のパスを結合しています。
isLink は、リンク項目かどうかを返します。
fileAttributesAtPath: traverseLink: は、指定したパスにあるファイルの属性ディクショナリを返すメソッドです。traverseLink: 引数は、リンクを追跡するかどうかで、YES ならリンク対象の項目のデータが返ってきます。ここでは、NO ですが、これだとリンクファイルそのものの属性が返ってきます。そして返されたディクショナリから、ファイルタイプの値をとりだし、それがシンボリックリンクファイルかどうかを調べています。返されたディクショナリには、作成日やサイズなど他にも多量の情報が入っています。
isReadable は、ファイルが読み出し可能かどうかを返します。
単に共有ファイルマネージャーに問い合わせているだけです。
isVisible は、ファイルが不可視項目かどうかを返します。
これは単に名前の先頭が「.」で始まるかどうかを調べているだけです。
lastPathComponent は、最後のパス成分を返します。
単に、インスタンス変数の相対パスの最後のパス成分を調べているだけです。
最後に、iconImageOfSize: は、この項目のアイコンを指定サイズで返します。
まずファイルのアイコンを取得します。NSWorkspace は、アプリケーションを起動したり、マウントを解除したりといったさまざまな雑用を行うクラスです。ファイルマネージャーの時と同様に、[NSWorkspace sharedWorkspace] で共有オブジェクトを取得して、それに対してメソッドを呼び出します。まず、それに対してファイルのアイコンを要求します。アイコンがないなら、そのタイプに対するアイコンを要求します。次に自身がリンクなら、リンクを表す矢印をアイコンの上に合成しています。途中、新しい空の画像を作成し、それに対して lockFocus し、そのなかに描画している所に注意してください。このように lockFocus と unlockFocus の間に描画メソッドを入れれば、その画像に描画できます。
これで、FSNodeInfo クラスのすべてのメソッドを調べました。
AppController クラスふたたび先ほどは、awakeFromNib メソッドと、reloadData: だけを見ました。残りのメソッドについて調べていきます。
まず、browser:numberOfRowsInColumn: を見てみます。このメソッドは受動的な委任が実装するものです。列における行の数を返します。
まず、自身で定義している fsPathToColumn: を呼び出しています。このメソッドは以下のようになります。
これは渡された列が 0(一番上または左)ならば、「/」を返し、そうでなければブラウザにその列までのパスを問い合わせて返しています。ここでいうパスはファイルシステムパスではなく、ブラウザのパスであることに注意してください。このクラスは、ブラウザパスをうまく利用してファイルシステムと一致させています。
browser:numberOfRowsInColumn: では、この戻り値のブラウザパスを相対パスとして、クラスメソッドを使って、新しい FSNodeInfo を自動解放オブジェクトとして作成しています。それから、そのオブジェクトに隠しファイルでない子項目の配列を作らせ、その数を返しています。
受動的な委任では、このメソッドで数を返すことによって、ブラウザが自動的に返された数を表示するためのマトリックスを作成して、表示が必要な項目に対して表示を要求することになります。能動的な委任では、列のマトリックスは委任が準備します。
各項目の表示に対して browser:willDisplayCell:atRow:column: が呼ばれます。
まず、そのセル項目の上位ディレクトリのパスを取得し、それを使って FSNodeInfo を得ています。そして、可視項目のリストを得て、その内容から番号でノードを取り出しています。最後に、セルのクラスとして設定したサンプル独自の FSBrowserCell のメソッド setAttributedStringValueFromFSNodeInfo: を呼び出して、その項目ノードから属性付き文字列値を作成させています。これはアイコン画像と属性付き文字列を生成させるためのものです。このクラスについては最後に説明します。
awakeFromNib で、このクラスは自身のインタンスをターゲットとして、シングルクリック、ダブルクリックのアクションを設定しました。ブラウサの項目がシングル・ダブルクリックされた時に、これらのメソッドが呼び出されることになります。まずシングルクリックです。
まずブラウザに選択されているセルの個数を問い合わせて、1 項目選択、複数選択、選択なしで処理を分けています。直接のメソッドではなく、NSArray を返してもらい、それに個数を問い合わせていることに注意してください。
1 項目選択の場合、まずブラウザに現在の選択範囲のパスを問い合わせます。次にそのパスを使って、FSNodeInfo を作成します。それからインスペクタに表示する文字列を作るメソッドをそのノードで呼び出しています。これは以下のようになります。
各行が長いですが、行われていることは単純です。まず最初に「Name:」とういうタイトルで属性付き文字列を作成します。この時、boldFontAttributes というこのクラスで定義されてるメソッドが呼ばれています。
これはシステムフォントサイズの太字フォントをフォント名属性としてもつ、1 項目だけの属性ディクショナリを作り、それを返しています。これにより「Name:」は太字となります。これと対応するメソッドは normalFontAttributes です。
これはシステムフォントをフォント名属性としてもつ、1 項目だけの属性ディクショナリを作って返します。これら 2 つのメソッドの意味がわかれば、attributedInspectorStringForFSNode: の残りも簡単に理解できます。単にフォントを変えながら、名前として最後のパス成分、「Type:」というタイトル、ファイルタイプを属性付き文字列に追加しているだけです。改行を追加するために、stringWithFormat: で改行が最後にくる書式文字列中にわざわざ文字列を入れているのに注意してください。書式文字列中の「%@」はオブジェクトを表します。
属性付き文字列を作成したら、次は FSNodeInfo クラスのメソッド iconImageOfSize: を使って、指定サイズのアイコン画像を作成させます。
複数選択の場合、@"Multiple Selection"、選択なしの場合、@"No Selection" という文字列を作成しているだけです。ここで、先ほどの属性付き文字列を作成するメソッド内では、autorelease されていたのに対して、この 2 つがされていないことに注意してください。これはこのサンプルのバグです。このままだと、複数選択、選択なしが起こるたびに、メモリ漏れが発生することになってしまいます。ビルドして実行を何度も行いたい人は、この 2 つを autorelease してやってください。このようにサンプルといえども完全でなく、特にメモリ関連のバグがときおり残っています。また、通常不必要なことを説明のためにあえてやっている場合もあるので、コピーして使うときは、十分注意してください。
つぎは、ダブルクリック時の動作を見てみます。
ブラウザから現在の選択範囲のパスを取得し、シングルクリック時のルーチンを呼び出し、それに情報を表示させます。それから NSWorkspace を使って、そこにあるファイルを開かせています。ディレクトタの場合、単にそれが Finder で表示されます。
これで AppController クラスについては、完全に理解できたはずです。最後に、ブラウザのセルとして設定されクラスを調べます。
FSBrowserCell クラスこのクラスのインターフェイス宣言の一部は以下のようになります。
NSBrowserCell のサブクラスであり、アイコン画像である NSImage を保持していることがわかります。@private は、このクラス以外で使われたくないインスタンス変数に使います。Objective-C 言語において、このほかに、@public、@protected があり、これらは、他から使えるもの、そのクラスとサブクラスでのみ使えるもの、を意味します。デフォルト(無指定)は @protected になっています。オブジェクト指向のカプセル化の観点からすると、@public は使うべきではなく、@private にしてアクセサを実装し、サブクラスもアクセサ経由にするというのが良いようですが、サブクラス内で変数が触れないのも不便なことが多いので、結果的に @protected が多用されることになります。
AppController において、セルの各項目を表示する前に呼ばれる委任メソッド browser:willDisplayCell:atRow:column: において、このクラスの setAttributedStringValueFromFSNodeInfo: が呼び出されていました。まず、これから見ていきます。
まず与えられたノードの最後のパス成分から文字列値を設定しています。次に、継承している NSCell のメソッド setAttributedStringValue: で属性付き文字列を設定しています。stringAttributesForNode: はこのクラスで定義されているもので、
まず、空の変更可能ディクショナリを作成し、それにフォント名を設定します。それだけではつまらないので、わざわざリンクの場合は下線をつけています。これは必要なこと、というより、さらに例を示すためです。
さて、setAttributedStringValueFromFSNodeInfo: に戻ると、属性付き文字列を設定した後で、アイコンを設定しています。setIconImage: もこのクラスで定義されているメソッドで、
まず元にあった画像を自動解放にして、それからコピーしています。その後で、画像サイズを設定しています。
さて、setAttributedStringValueFromFSNodeInfo: で、アイコン画像をインスタンス変数に収めた後は、読みとり可能な場合だけ有効になるようにしています。それから、ノードの葉を設定しています。これはノードクラスで初期化時に子が設定されず、子がなかった場合、それを設定することも行われていないため、これを呼び出すことで同時にそれも設定されるようにしています。これで、このメソッドは終わりです。基本的に表示が行われる前に表示に必要なデータを準備しているメソッドであることがわかったと思います。
他のメソッドは、基本的に継承メソッドです。全体的な説明については『Cocoa のためのコントロールとセルプログラミングトピック』の「NSCell のサブクラスの作成」その他の記事を見てください。ここで触れられているdrawInteriorWithFrame:inView: がこのクラスで実装されています。これがブラウザのセルの内部を実際に描いています。
ちょっとややこしそうですが、順を追えば簡単に理解できます。最初に画像サイズをローカル変数 imageSize に入れています。次に渡されたセルのフレームを2つに分割しています。先頭からアイコンまでの空間+アイコンサイズ+アイコンからテキストまでのサイズをもつ長方形と、そこから最大xまでの2つに分割しています。それから、左側の長方形のサイズをアイコンサイズに変えています。この長方形はアイコンを
描くときに使うので、アイコンサイズぴったりにしています。
つぎに、コントロールが反転されているかどうか判らないため、それにしたがって調整を行っています。反転の場合は、アイコンを描き始める場所まで原点を動かしています。この時、テキスト部分との高さを足したり引いて割っているのは、テキスト長方形の高さとアイコンサイズの高さが同じではないからで、空間を上下で同じにして、テキストの中央にアイコンが描かれるようにしています。
つぎに強調される場合の背景色を描いています。これは選択している時に青色で表示されているものです。ただし、サンプルのブラウザでは、一番左にあるもの以外は、灰色で強調されることになります。この色を決定しているのが、NSBrowserCell で定義されている highlightColorInView: メソッドです。ブラウザでは同様な動作をすることがあるので、このメソッドで適切な色を返すようになっています。つぎにその色を設定して、それで背景を描画しています。それからその上にアイコン画像を合成しています。
テキスト部分に関しては、ブラウザセルのメソッドにまかせています。以前に setAttributedStringValueFromFSNodeInfo: 内で属性付きの文字列が設定されているので、これが適切に動作します。
残りのメソッドは、継承メソッドのオーバーライドです。branchImage と highlightedBranchImage はクラスメソッドで、それぞれ通常と強調状態の枝項目の画像を返します。デフォルトは右方向の三角形です。このサンプルでは枝項目の前に三角形を表示させたくないので nil を返しています。
cellSizeForBounds: は NSCell から継承されているメソッドで、渡された長方形に最大サイズを限定して、セルの内容を表示するために必要な最低限の長方形を返します。
このクラスでアイコンを扱っているため、上位クラスやブラウザはアイコンが表示されていることについて関知していません。そのため、属性付き文字列だけを表示するのに必要な空間を設定します。このクラスでは、アイコンを表示するため、単に文字の高さだけにもとづいてサイズを設定するわけにはいきません。ここでは、テキストだけで計算された長方形に対して、アイコンの幅とアイコンの高さにもとづいてサイズを再設定しています。
これで、このクラスのメソッドについて理解できたと思います。
簡単なように見えて奥が深いサンプルです。特に独自描画を行うセルについての参考資料となっています。ブラウザ以外のセルについて、そのまま応用できるものではないですが、独自セルがどのように実装されているか、少しわかると思います。
このサンプルでは、受動的なブラウザを使用していることに注意してください。能動的なブウラザ委任では、さらに列内のマトリック全体を変えることもできます。また、セルのサブクラスの独自描画では、drawInteriorWithFrame:inView: ではなく、drawWithFrame:inView: も使えることに気をつけてください。
管理人:神吉 秀典 E-mail: