Mac用USBデバイス-99 Cocoaバインディングを使おう [Mac用USBデバイス工作]
2週間近くほったらかしにしてたら、何やってたかほんとにきれいさっぱり忘れた。「鋭い忘却力!」なんて言って笑ってられない、マジで。昨日丸一日かけて思い出す努力をした。
USBのデスクリプタを自動生成するアプリを書こうとしていた。UIリッチなアプリになるのでなるべく簡単になるようにCocoaバインディングのコントローラクラスであるNSTreeControllerを使って記述量を減らそうと思ったが、なかなか勝手な構造のクラス定義ではうまくいかない。モデルが内在する構造とNSTreeControllerが期待する構造とにギャップがあると、何らかの形でその間の調整をする必要がある。
ところがここで別の問題がある。NSTreeControllerは
今回のアプリの場合、デスクリプタの入れ子関係には制限が多い。例えば
途中に挿入する場合や削除する場合にも
などで同じことをする。ちなみにremoveChild:メソッドはない(あたりまえか)。それ以外にNSIndexPathを使って直接指定するメソッドもあるが、やることは同じ(おそらくadd:メソッドなどはNSIndexPathを使ったメソッドを内部で呼んでいるんだろう)。
例えば要素に異なるインスタンスを追加するメソッドを実装する。
こうすればNSOutlineView上で選択された位置に新しいインスタンスが追加される。
ところが大きな問題がある。このままでは追加されたインスタンスがNSOutlineViewで表示されない。これはadd:メソッドなどを経由すればキー値オブザービングで自動的に反映されるが、こういう自前のメソッドでインスタンスを追加してしまうとNSOutlineViewに通知が発行されないためで別途データをリロードするメソッドをNSOutlineViewに対して投げるか、通知を明示的に起動する必要がある。これでは何のためにCocoaバインディングを使うのわからなくなってしまう。
もうちょっと何か工夫が必要。
USBのデスクリプタを自動生成するアプリを書こうとしていた。UIリッチなアプリになるのでなるべく簡単になるようにCocoaバインディングのコントローラクラスであるNSTreeControllerを使って記述量を減らそうと思ったが、なかなか勝手な構造のクラス定義ではうまくいかない。モデルが内在する構造とNSTreeControllerが期待する構造とにギャップがあると、何らかの形でその間の調整をする必要がある。
5.3 NSTreeControllerを使う
NSTreeControllerを使ってデスクリプタのマスタ構造の追加や削除を制御して、その表示にNSOutlineViewと結びつけたい。ところがここで別の問題がある。NSTreeControllerは
- 要素クラス(デフォルトではNSMutableDictionary)
- 要素の配列
- それぞれの要素が保持する子供の配列
[[ElementClass alloc] init];生成できないといけない。つまり要素のオブジェクトを作るときに引数を渡すことはできない。
今回のアプリの場合、デスクリプタの入れ子関係には制限が多い。例えば
- DEVICEデスクリプタの子供には
- CONFIGURATION
- DEVICE_QUALIFIER
- OTHER_SPEED
- CONFIGURATIONデスクリプタの子供にはINTERFACEデスクリプタしかなれない
- その他、いろいろ
5.3.1 NSTreeControllerが要素を追加するとき
NSTreeControllerは要素を追加するとき、何をするのかを調べてみる。ドキュメントには- NSTreeControllerのadd:メソッドが呼ばれる
- NSTreeControllerはsuper(NSObjectController)にnewObjectメソッドを投げる
- newObjectメソッドはsetObjectClass:で設定されているクラスのインスタンスを作って返す
- NSTreeControllerはそのインスタンスを選択されたレベルの後ろに追加する
- キー値オブザーバに通知を投げる
途中に挿入する場合や削除する場合にも
insert: |
insertChild: |
remove: |
5.3.2 異なるインスタンスを追加する方法?
これだけでは追加する場所によって追加できるインスタンスを変えることはできない。そこでなにか工夫が必要になる。とりあえず一番簡単なのはこういった専用メソッドを経由しない方法が考えられる。例えば要素に異なるインスタンスを追加するメソッドを実装する。
- (void)addFirstInstance; - (void)addSecondInstance;などを作って、このメソッド中でインスタンスを作って自分で追加する。追加用のボタンウィンドウに貼付けてそのActionInvocationのtargetとしてNSTreeControllerのselectionにこれらのメソッドをバインドする。
こうすればNSOutlineView上で選択された位置に新しいインスタンスが追加される。
ところが大きな問題がある。このままでは追加されたインスタンスがNSOutlineViewで表示されない。これはadd:メソッドなどを経由すればキー値オブザービングで自動的に反映されるが、こういう自前のメソッドでインスタンスを追加してしまうとNSOutlineViewに通知が発行されないためで別途データをリロードするメソッドをNSOutlineViewに対して投げるか、通知を明示的に起動する必要がある。これでは何のためにCocoaバインディングを使うのわからなくなってしまう。
もうちょっと何か工夫が必要。
2010-05-12 22:27
nice!(1)
コメント(0)
トラックバック(0)
コメント 0