私は次のことをテストしたり試みたりしていませんが、とにかく試してみると思いました.
まず、NS*Controller を使用して NSTableView または NSOutlineView で複雑なものを管理するのは苦痛であり、簡潔さと引き換えに正確な制御を犠牲にします。このような状況で動作に問題がある場合は、独自のカスタム コントローラーにデータソースとデリゲート プロトコル (NSTableViewDataSource、NSTableViewDelegate または NSOutlineViewDataSource、NSOutlineViewDelegate) を実装することを検討してください。
第二に、KVO 通知の発行に関する Warren Burton のコメントは適切です。これは、とにかくそのコレクションを制御 (および監視) しているため、責任のあるコントローラー (NSTreeController) に変更について伝える必要があるためです。さらに言えば、NSTreeController の add/insert/remove メソッドを直接使用する必要があります。現在行っている方法 (無効にするたびに構造全体を叩き、後でリセットする) では、ツリー全体がリロードされます。コントローラーはそのコレクションを監視しているため、アウトライン ビューにそれ自体を更新するように指示しています。これにより、最初に空のアウトラインが表示され、その後、アウトラインのさらに展開されたバージョンが表示される可能性があります。これにより、ユーザーの展開状態が失われます。ツリーコントローラーを介したモデルにより、よりスマートで、
3 番目に、上記の 2 番目の点を利用して、NSTreeController をサブクラス化し、追加/挿入/削除メソッドをオーバーライドして次のことを行うことを検討できます。
- アウトライン ビューにその
-visibleRect
.
- super を呼び出して変更を開始します。
- アウトラインビューを に伝え
-scrollRectToVisible:
ます。
手順 3 の呼び出しをメイン スレッドでスケジュールすることにより、呼び出しを遅らせる必要がある場合があります (そのため、実行ループを介した現在のトリップの後に発生します)。または、別の方法として、ステップ 3 を可視の rect をどこかに保存し、NSOutlineViewDelegate-outlineView:didAdd/RemoveRowView:forRow:
メソッドを実装してこのフラグをチェックし、Rect-scrollRectToVisible:
がゼロでない場合はそこから呼び出します (スクロールを調整しようとしないように NSZeroRect にリセットすることを忘れないでください)アウトライン行が追加または削除されるたびに)。
不格好ですが、NSTreeController を維持できる妥当な (?) パスです。
4番目に、代わりに(そして私が行く方法)、NSTreeControllerを完全に削除し、NSOutlineViewDataSource(およびNSOutlineViewDelegate)プロトコルを独自のコントローラークラスに実装し、そのコントローラーにツリー構造への追加または削除を直接処理させることができます。その後、KVO のタイミングを気にする必要がないため、よりクリーンになります。ノードを追加するたびに、表示されている四角形を確認し、アウトライン ビューを更新してから、同じメソッド内でスクロールをすべて調整し、実行ループをトリップすることができます。
これがお役に立てば幸いです。:-)