Sample CodemacOSReviewed 2026-07-21View on Apple Developer

Navigating Hierarchical Data Using Outline and Split Views

At a glance

Item Summary
Purpose Present file-like hierarchy in a source-list outline and swap an appropriate detail view in a split view.
Architecture Node model + NSTreeController/outline controller + split/detail controllers, coordinated through notifications and child containment.
Scope Also demonstrates editing, menus, drag/drop, expansion, and restoration through extensions on the outline controller.

Project structure

SourceView/
├── Node.swift
├── OutlineViewController.swift
├── OutlineViewController+{Delegate,Helpers,DragDrop,Expansion,Restoration}.swift
├── SplitViewController.swift
├── WindowViewController.swift
└── {Icon,File,Image}ViewController.swift

The large outline controller is split by framework capability. Detail controllers remain small and presentation-specific.

Overall architecture

Reference code

SourceView/SplitViewController.swift:80 — the split controller reacts to selection and asks the outline owner for the correct detail controller.

    @objc
    private func handleSelectionChange(_ notification: Notification) {
        // ...
    }

Ownership and state

Ownership evidence

SourceView/OutlineViewController.swift:46 — one controller owns observation and the reusable detail-controller set.

private var treeControllerObserver: NSKeyValueObservation?
@objc dynamic var contents: [AnyObject] = []

private var iconViewController: IconViewController!
private var fileViewController: FileViewController!
private var imageViewController: ImageViewController!

The tree controller mutates arranged Node objects. The outline controller owns hierarchy commands and cached detail candidates. The split controller owns only the currently embedded child relationship; the window controller snapshots selection for command validation.

Class and protocol design

Type Responsibility
Node / NodeType Codable tree data and derived file/display capabilities.
OutlineViewController Populate, select, edit, add, remove, drag, drop, and map selection to detail.
SplitViewController Replace the active detail child while preserving split-view behavior.
WindowViewController Toolbar commands, progress, and menu validation.
Detail controllers Render a selected URL, image, icon collection, or multiple selection.

Most protocols are AppKit contracts (NSTextFieldDelegate, validation, outline delegates). CustomMenuDelegate is the small app-defined seam for contextual menu construction.

Access control

Boundary Effect and rationale
private outlets, observers, helper methods, and cached detail controllers Keeps tree and child-controller invariants with their owner.
@objc dynamic contents and Node.children Makes model state visible to Cocoa bindings/KVO; it remains internal to the module.
Implicit internal types and cross-file extensions Lets the feature be divided into capability files without exporting a library API.
Private toolbar identifier extension Prevents raw UI identifiers from becoming general dependencies.

SourceView/Node.swift:19 shows the internal model and dynamic children property; SourceView/WindowViewController.swift:188 shows the file-private identifier namespace.

Logic ownership and placement

Logic Owner
Tree population and mutations OutlineViewController and helpers
Row display, contextual menu, drag/drop, restoration Named OutlineViewController+... extensions
Detail selection policy OutlineViewController.viewControllerForSelection
Child embedding/removal SplitViewController
Toolbar/menu enablement WindowViewController
File-derived display properties Node and URL helpers

Design patterns

Pattern Evidence Purpose
MVC SourceView/Node.swift:19, SourceView/OutlineViewController.swift:11 Separates hierarchy data from AppKit coordination.
Observer SourceView/OutlineViewController.swift:483 Converts tree selection KVO into feature-level notification.
Child view controller SourceView/SplitViewController.swift:55 Swaps detail content without replacing the split controller.
Capability extensions SourceView/OutlineViewController+DragDrop.swift:11 Organizes a large framework-facing controller by concern.
Codable adapter SourceView/OutlineViewController.swift:307 Decodes plist hierarchy into Node values.

Naming conventions

  • NodeType and derived is.../can... properties express hierarchy capability.
  • *ViewController names map directly to screen roles; +Capability files map to AppKit behaviors.
  • Notification names are scoped in nested NotificationNames structures rather than scattered strings.

Architecture takeaways

  • Let the outline controller own hierarchy policy and the split controller own containment mechanics.
  • Cache reusable detail controllers, but keep only one actively embedded.
  • Translate low-level KVO into a feature event at a clear boundary.
  • Split framework-heavy controllers by capability while retaining one state owner.

Source map

Source Role
SourceView/Node.swift:19 Tree model
SourceView/OutlineViewController.swift:11 Hierarchy owner
SourceView/SplitViewController.swift:19 Detail containment
SourceView/WindowViewController.swift:10 Window command UI
SourceView/FileViewController.swift:20 Representative detail binding