SSブログ

Mac用USBデバイス-99 Cocoaバインディングを使おう [Mac用USBデバイス工作]

2週間近くほったらかしにしてたら、何やってたかほんとにきれいさっぱり忘れた。「鋭い忘却力!」なんて言って笑ってられない、マジで。昨日丸一日かけて思い出す努力をした。

USBのデスクリプタを自動生成するアプリを書こうとしていた。UIリッチなアプリになるのでなるべく簡単になるようにCocoaバインディングのコントローラクラスであるNSTreeControllerを使って記述量を減らそうと思ったが、なかなか勝手な構造のクラス定義ではうまくいかない。モデルが内在する構造とNSTreeControllerが期待する構造とにギャップがあると、何らかの形でその間の調整をする必要がある。

5.3  NSTreeControllerを使う

NSTreeControllerを使ってデスクリプタのマスタ構造の追加や削除を制御して、その表示にNSOutlineViewと結びつけたい。

ところがここで別の問題がある。NSTreeControllerは
  • 要素クラス(デフォルトではNSMutableDictionary)
  • 要素の配列
  • それぞれの要素が保持する子供の配列
でツリー構造ができていると仮定している。要素は単一のクラスで
    [[ElementClass alloc] init];
生成できないといけない。つまり要素のオブジェクトを作るときに引数を渡すことはできない。

今回のアプリの場合、デスクリプタの入れ子関係には制限が多い。例えば
  • DEVICEデスクリプタの子供には
    • CONFIGURATION
    • DEVICE_QUALIFIER
    • OTHER_SPEED
    だけしかなれない
  • CONFIGURATIONデスクリプタの子供にはINTERFACEデスクリプタしかなれない
  • その他、いろいろ
などの構造が決まっている。このままではNSTreeControllerとの相性は良くない。ちょっと工夫が必要になる。

5.3.1  NSTreeControllerが要素を追加するとき

NSTreeControllerは要素を追加するとき、何をするのかを調べてみる。ドキュメントには
  1. NSTreeControllerのadd:メソッドが呼ばれる
  2. NSTreeControllerはsuper(NSObjectController)にnewObjectメソッドを投げる
  3. newObjectメソッドはsetObjectClass:で設定されているクラスのインスタンスを作って返す
  4. NSTreeControllerはそのインスタンスを選択されたレベルの後ろに追加する
  5. キー値オブザーバに通知を投げる
ということをするらしいことが書いてある。子供を追加するときはadd:メソッドの代わりにaddChild:メソッドを投げれば、同じようにインスタンスを作って選択されたオブジェクトの子供に追加する。

途中に挿入する場合や削除する場合にも
insert:
insertChild:
remove:
などで同じことをする。ちなみにremoveChild:メソッドはない(あたりまえか)。それ以外にNSIndexPathを使って直接指定するメソッドもあるが、やることは同じ(おそらくadd:メソッドなどはNSIndexPathを使ったメソッドを内部で呼んでいるんだろう)。

5.3.2  異なるインスタンスを追加する方法?

これだけでは追加する場所によって追加できるインスタンスを変えることはできない。そこでなにか工夫が必要になる。とりあえず一番簡単なのはこういった専用メソッドを経由しない方法が考えられる。

例えば要素に異なるインスタンスを追加するメソッドを実装する。
- (void)addFirstInstance;
- (void)addSecondInstance;
などを作って、このメソッド中でインスタンスを作って自分で追加する。追加用のボタンウィンドウに貼付けてそのActionInvocationのtargetとしてNSTreeControllerのselectionにこれらのメソッドをバインドする。

こうすればNSOutlineView上で選択された位置に新しいインスタンスが追加される。

ところが大きな問題がある。このままでは追加されたインスタンスがNSOutlineViewで表示されない。これはadd:メソッドなどを経由すればキー値オブザービングで自動的に反映されるが、こういう自前のメソッドでインスタンスを追加してしまうとNSOutlineViewに通知が発行されないためで別途データをリロードするメソッドをNSOutlineViewに対して投げるか、通知を明示的に起動する必要がある。これでは何のためにCocoaバインディングを使うのわからなくなってしまう。

もうちょっと何か工夫が必要。
nice!(1)  コメント(0)  トラックバック(0) 

nice! 1

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

献立05/12献立05/13 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。