Question

If I changed my NSOutlineView from using bindings and an NSTreeController to having a data source and a delegate, how would I automatically update the NSOutlineView, if my model tree changes? Should I observe the childNodes property of every single node in my tree with my controller and trigger a reload when a change occurs? Or is there another way?

Was it helpful?

Solution

That's one way. Another way would be for the model to post notifications when it changes and have your controller observe those.

Also, a model doesn't typically change spontaneously. Usually, the change is initiated outside of the model in response to some event. A controller is usually doing that. So, that controller could also provoke an update to the outline view. (There may be multiple controllers, so maybe the controller that initiates the model change just informs a window or view controller, which would be responsible for updating the outline view.)

OTHER TIPS

I asked a similar question that was marked as duplicate here: Recommended Pattern for Observing Changes in Tree Structure [duplicate]

I wanted to avoid using NSTreeController as it means you lose control of animations when updates occur.

I have an MVVM set up. My model is a graph, my view model is a tree. There is a one-one relationship between any tree nodes and a graph node. As detailed in the question above, there is obviously a many-one relationship between the tree nodes and an outline view.

So, I settled with...

The view-model tree nodes need to know when their children are updated, so I used KVO of the associated graph node to catch when children are added or removed.

For the outline view update I settled on a model-view delegate that I implement on the view-controller. Each tree-node in the view model can call delegate methods on the tree root when children are added or removed. This felt the clearest approach to me, and easily debuggable. I didn't want chains of things happening behind the scenes.

The final outline view update call felt satisfyingly simple:

func itemsInserted(atIndexes indexes: IndexSet, forParent parent: ECViewModelNode) {
        outlineView?.insertItems(at: indexes, inParent: parent, withAnimation: .slideDown)
    }

At the table-cell-view level I bind directly to the details of the graph model nodes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top