NSOutlineViewをバインディングとNSTreeControllerの使用からデータソースとデリゲートの使用に変更した場合、モデルツリーが変更された場合、NSOutlineViewを自動的に更新するにはどうすればよいですか?ツリー内のすべてのノードのchildNodesプロパティをコントローラーで監視し、変更が発生したときにリロードをトリガーする必要がありますか?または別の方法はありますか?
2 に答える
それが1つの方法です。もう1つの方法は、モデルが変更されたときに通知を投稿し、コントローラーにそれらを監視させることです。
また、モデルは通常、自発的に変化することはありません。通常、変更は何らかのイベントに応じてモデルの外部で開始されます。コントローラーは通常それを行っています。そのため、そのコントローラーは、アウトラインビューの更新を引き起こす可能性もあります。(複数のコントローラーが存在する可能性があるため、モデルの変更を開始するコントローラーは、アウトラインビューの更新を担当するウィンドウまたはビューコントローラーに通知するだけです。)
ここで重複としてマークされた同様の質問をしました:ツリー構造の変化を観察するための推奨パターン[重複]
更新が発生するとアニメーションの制御が失われることを意味するため、NSTreeControllerの使用は避けたかったのです。
MVVMをセットアップしました。私のモデルはグラフであり、私のビューモデルは木です。ツリーノードとグラフノードの間には1対1の関係があります。上記の質問で詳しく説明したように、ツリーノードとアウトラインビューの間には明らかに多対1の関係があります。
だから、私は落ち着きました...
ビューモデルツリーノードは、子がいつ更新されるかを知る必要があるため、関連するグラフノードのKVOを使用して、子が追加または削除されたときをキャッチしました。
アウトラインビューの更新では、ビューコントローラーに実装するモデルビューデリゲートを決定しました。ビューモデルの各ツリーノードは、子が追加または削除されたときにツリールートのデリゲートメソッドを呼び出すことができます。これは私にとって最も明確なアプローチであり、簡単にデバッグできると感じました。私は舞台裏で物事の連鎖が起こることを望んでいませんでした。
最終的なアウトラインビューの更新呼び出しは、満足のいくように単純であると感じました。
func itemsInserted(atIndexes indexes: IndexSet, forParent parent: ECViewModelNode) {
outlineView?.insertItems(at: indexes, inParent: parent, withAnimation: .slideDown)
}
テーブルセルビューレベルでは、グラフモデルノードの詳細に直接バインドします。